vim mapping для запуска c ++ с необязательным входным файлом - PullRequest
1 голос
/ 11 июля 2019

Я настраиваю файл vimrc для конкурентного программирования на c ++.

autocmd filetype cpp nnoremap <F5> :w <CR> 
                                   :!g++ -o %:r % <CR> :!./%:r < input.txt <CR>

Следующее сопоставление, когда я нажимаю F5, сохраняет, компилирует (%: r - имя файла без .cpp) и запускается с файлом input.txt.

Однако не у каждого файла cpp есть input.txt, поэтому я хочу передать input.txt только тогда, когда input.txt существует в текущем каталоге.

Подводя итог, каков наилучший способ проверки файлов во время сопоставления?

Ответы [ 3 ]

2 голосов
/ 11 июля 2019

Если вы не работаете в среде, где gnu make недоступен или плохо настроен (mingw), вам не понадобится Makefile для монофайловых проектов. Они не являются обязательными в этом случае, и IMO больше хлопот, чем что-либо еще.

Компиляция лучше всего выполняется с:

:make %<

Таким образом, любые ошибки напрямую переходят к окнам быстрого исправления. Это повысит вашу производительность при поиске ошибок (:h quickfix). Кроме того, независимо от того, используется ли ваш текущий файл на C, C ++, Fortran ... или на любом другом языке, распознаваемом по умолчанию конфигурацией gnumake, вам не нужно указывать компилятор, который вы хотите использовать, в зависимости от текущего типа файла. Если вы действительно хотите выбрать другой компилятор для C ++, например, вы можете использовать

:let $CXX ='clang++'
" $CC for C, and so on

А если вы хотите изменить параметры компиляции

:let $CXXFLAGS = '-std=c++17 -Wall -Werror'
" $CFLAGS for C, $LDLIBS, $LDFLAGS for the linker, and so on

Обратите внимание, что если у вас есть Makefile, он будет автоматически использован.

Цепочка с исполнением

:!make %< && ./%< действительно достаточно просто, чтобы соединить оба шага. Увы, у нас нет прямого эквивалента с :make. Мы должны проанализировать список быстрых исправлений, чтобы увидеть, были ли какие-либо проблемы

Если filter(getqflist(), 'v:val.valid != 0') не пусто, мы можем узнать, были ли обнаружены проблемы. Но это не говорит, являются ли они предупреждениями или ошибками. Мы можем получить полную информацию со следующим

" From my build-tools-wrapper plugin
function! lh#btw#build#_get_metrics() abort
  let qf = getqflist()
  let recognized = filter(qf, 'get(v:val, "valid", 1)')
  " TODO: support other locales, see lh#po#context().tranlate()
  let errors   = filter(copy(recognized), 'v:val.type == "E" || v:val.text =~ "\\v^ *(error|erreur)"')
  let warnings = filter(copy(recognized), 'v:val.type == "W" || v:val.text =~ "\\v^ *(warning|attention)"')
  let res = { 'all': len(qf), 'errors': len(errors), 'warnings': len(warnings) }
  return res
endfunction

Исходя из этого, мы можем решить остановиться только на ошибках или на ошибках и предупреждениях.

Дополнительные входы

С помощью filereadable() мы можем знать, находится ли здесь входной файл.

Таким образом, оно становится:

let exec_line = '!./' . expand('%<') " we could also use the complete path instead
let input = expand('%:p:h')/.'input.txt'
if filereadable(input)
    let exec_line .= ' < ' . input
endif
exe exec_line

Если вы хотите перенаправить результат в терминал:, на этот раз, к сожалению, перенаправление не может быть использовано с Vim (хотя он работает с nvim)

TL; DR

Окончательный код (учитывая предыдущую функцию для обнаружения ошибок и предупреждений) становится.

function s:build_and_run(file) abort
  let tgt  = fnamemodify(a:file, ':r')
  " to make sure the buffer is saved
  exe 'update ' . a:file
  exe 'make ' . tgt
  if lh#btw#build#_get_metrics().errors
    echom "Error detected, execution aborted"
    copen
    return
  endif

  let path = fnamemodify(a:file, ':p:h')
  let exec_line = '!./' . tgt
  let input = path.'/input.txt'
  if filereadable(input)
    let exec_line .= ' < ' . input
  endif
  exe exec_line
endfunction

nnoremap µ :<C-U>call <sid>build_and_run(expand('%'))<cr>
1 голос
/ 11 июля 2019

Что вы подразумеваете под запуском его с входным файлом?Я думаю, вы должны рассмотреть возможность использования Makefile.Это место, где моделируются все зависимости сборки (например, включает в себя, пути ссылок, выполнение тестов и т.Makefile

autocmd filetype cpp nnoremap <F5> :w <CR> :!make all<CR>
0 голосов
/ 11 июля 2019

Как уже упоминалось @ schorsch312, makefile будет более безопасным и эффективным.

Благодаря @Botje работает приведенная ниже конфигурация

autocmd filetype cpp nnoremap <F5> :w <CR>
                               :!g++ -o %:r % && cat input.txt 2> /dev/null \| ./%:r <CR>

Вот несколько проблем, с которыми я столкнулся

  • noremap: нерекурсивное отображение только для нормального режима ( больше )
  • : клавиша ввода (обычно используется с отображением команд последней строки)
  • &&: запускается только при успешной компиляции ( больше )
  • 2> dev / null: игнорировать ошибку, когда input.txt не существует ( more )
  • Ты должен сбежать | или используйте вместо
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...