Как прокомментировать макрос VIM - PullRequest
4 голосов
/ 16 декабря 2010

Можно ли комментировать макрос и воспроизводить его.

Пример

вместо

  dddwj

Я хотел бы прокомментировать и выполнить следующий фрагмент

  dd # Delete line
  dw # Delete word
  j  # Move to next line

Некоторый фон

Мы используем PICT для генерации входных данных тестового примера (тестирование всех пар). Поскольку это итеративный процесс, макрос для генерации кода необходимо настроить между последующими запусками. Трудно изменить макрос, когда все в одной строке, без комментариев.

Результат выполнения PICT может выглядеть примерно так:

1 cInstallationX Pu380
2 cInstallationY U400

, которые можно преобразовать в тестовые наборы с макросом

procedure TWatchIntegrationTests.Test1;
begin
  //***** Setup
  builder
    .withInstallation(cInstallationX)
    .withIsotope(Pu380)
  .Build;

  //***** Execute
  CreateAndCollectWatches;

  //***** Verify
  VerifyThat
    .toDo;
end;

procedure TWatchIntegrationTests.Test2;
begin
  //***** Setup
  builder
    .withInstallation(cInstallationY)
    .withIsotope(U400)
  .Build;

  //***** Execute
  CreateAndCollectWatches;

  //***** Verify
  VerifyThat
    .toDo;
end;

Ответы [ 2 ]

11 голосов
/ 16 декабря 2010

Я не знаю хорошего способа сделать это с помощью макросов, но я вижу несколько вариантов, которые могут помочь:

Интенсивное использование «нормального» * ​​1003 * Это самый близкий к вашему макросу вариант, но не очень приятный: сделайте ваш сохраненный файл похожим на это: " Delete line normal dd " Delete word normal dw " Move to next line normal j Сложная замена

При этом используются регулярные выражения, но эти регулярные выражения хорошо комментируются (это основано на вашем реальном примере).

let pattern  = '^'              " Start of line
let pattern .= '\(\d\+\)'       " One or more digits (test number)
let pattern .= '\s\+'           " Space or tab as delimiter
let pattern .= '\(\k\+\)'       " Installation name
let pattern .= '\s\+'           " Space or tab as delimiter
let pattern .= '\(\a\+\d\+\)'   " One or more alphabetic characters, then one or more spaces (isotope)
let pattern .= '\s*$'           " Any spaces up to the end of the line

let result  = 'procedure TWatchIntegrationTests.Test\1;\r'
let result .= 'begin\r'
let result .= '  //***** Setup\r'
let result .= '  builder\r'
let result .= '    .withInstallation(\2)\r'
let result .= '    .withIsotope(\3)\r'
let result .= '  .Build;\r'
let result .= '\r'
let result .= '  //***** Execute\r'
let result .= '  CreateAndCollectWatches;\r'
let result .= '\r'
let result .= '  //***** Verify\r'
let result .= '  VerifyThat\r'
let result .= '    .toDo;\r'
let result .= 'end;\r'

exe '%s!' . pattern . '!' . result . '!'

Вставьте это в функцию

Учитывая, что это становится довольно сложным, я бы, вероятно, сделал это таким образом, поскольку это дает больше места для настройки. На мой взгляд, вы хотите разбить линию на пустое пространство и использовать три поля, примерно так:

" A command to make it easier to call
" (e.g. :ConvertPICTData or :'<,'>ConvertPICTData)
command! -range=% ConvertPICTData <line1>,<line2>call ConvertPICTData()

" Function that does the work
function! ConvertPICTData() range
    " List of lines producing the required template
    let template = [
                \ 'procedure TWatchIntegrationTests.Test{TestNumber};',
                \ 'begin',
                \ '  //***** Setup',
                \ '  builder',
                \ '    .withInstallation({Installation})',
                \ '    .withIsotope({Isotope})',
                \ '  .Build;',
                \ '',
                \ '  //***** Execute',
                \ '  CreateAndCollectWatches;',
                \ '',
                \ '  //***** Verify',
                \ '  VerifyThat',
                \ '    .toDo;',
                \ 'end;',
                \ '']

    " For each line in the provided range (default, the whole file)
    for linenr in range(a:firstline,a:lastline)
        " Copy the template for this entry
        let this_entry = template[:]

        " Get the line and split it on whitespace
        let line = getline(linenr)
        let parts = split(line, '\s\+')

        " Make a dictionary from the entries in the line.
        " The keys in the dictionary match the bits inside
        " the { and } in the template.
        let lookup = {'TestNumber': parts[0], 
                    \ 'Installation': parts[1],
                    \ 'Isotope': parts[2]}

        " Iterate through this copy of the template and 
        " substitute the {..} bits with the contents of
        " the dictionary
        for template_line in range(len(this_entry))
            let this_entry[template_line] = 
                        \ substitute(this_entry[template_line], 
                        \   '{\(\k\+\)}', 
                        \   '\=lookup[submatch(1)]', 'g')
        endfor

        " Add the filled-in template to the end of the range
        call append(a:lastline, this_entry)
    endfor

    " Now remove the original lines
    exe a:firstline.','.a:lastline.'d'
endfunction

Сделай это на питоне

Это задача, которую, вероятно, легче выполнить в python:

import sys

template = '''
procedure TWatchIntegrationTests.Test%(TestNumber)s;
begin
  //***** Setup
  builder
    .withInstallation(%(Installation)s)
    .withIsotope(%(Isotope)s)
  .Build;

  //***** Execute
  CreateAndCollectWatches;

  //***** Verify
  VerifyThat
    .toDo;
end;
'''

input_file = sys.argv[1]
output_file = input_file + '.output'

keys = ['TestNumber', 'Installation', 'Isotope']

fhIn = open(input_file, 'r')
fhOut = open(output_file, 'w')

for line in fhIn:
    parts = line.split(' ')
    if len(parts) == len(keys):
        fhOut.write(template % dict(zip(keys, parts)))
fhIn.close()
fhOut.close()

Чтобы использовать это, сохраните его как (например) pict_convert.py и запустите:

python pict_convert.py input_file.txt

В результате получится input_file.txt.output.

4 голосов
/ 16 декабря 2010

Прежде всего позвольте мне отметить, что @Al опубликовал несколько отличных решений, и я предлагаю вам использовать их, а не то, что я собираюсь опубликовать.Тем более, что это, кажется, не работает при всех обстоятельствах (по причинам, которые я не понимаю).

Сказав это, следующее, кажется, делает то, что вы хотите, по крайней мере в этом случае.Предполагается, что <Space> в обычном режиме не используется для перемещения курсора.Сопоставляет его с :", где " - символ комментария для режима cmline.Что означает <Space> - это символ, который начинает комментарий в этом случае.Новая строка в конце останавливает комментарий.* * * * * * * * * * * * * * * * * * * * * * 10 * просто для того, чтобы прояснить, что мы имеем дело с комментариями.(^[ следует вводить как один управляющий символ).

:nmap <Space> :"
iHallo wereld^[             # Insert text (in dutch, better change that)
Fe                          # Move backwards to e
x                           # Delete
;                           # Move to next e
ro                          # Change to o
Fa                          # Move backwards to a
re                          # Change to e
A!^[                        # Add exclamation mark
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...