SNR

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

Понадобилось мне сделать простую, вроде бы, вещь: привести к общему виду все функции в HwGUI - поставить в названиях префикс "hwg_", ну и, соответственно, сделать автоматический search and replace - изменить во всех исходниках вызовы этих функций. Казалось бы, средств для этого более, чем достаточно. Любой текстовый редактор это делает, и утилит всяких для этого немало. Но, как часто бывает, при ближайшем рассмотрении выяснилось, что не все так просто, везде не хватает чего-то важного.

Что мне, собственно, надо:
    - чтобы операция производилась автоматически с группой файлов, находящихся, возможно, во вложенных каталогах;
    - чтобы можно было задать произвольное количество пар найти/заменить, а не производить эту операцию для каждой пары отдельно;
    - чтобы менялось именно то, что надо, например, строка cSelectFile := SelectFile( par1,... ) ,была заменена на cSelectFile := hwg_SelectFile( par1,... ), это обычно регулируется опцией "Whole words" - "Целые слова".

Я скачал несколько утилит по ссылкам с Яндекса и попробовал их. Некоторые пришлось устанавливать, что само по себе для такой простой программы выглядит странно и поэтому немного раздражает. Но везде чего-то не хватало, чаще всего пункта 2 моих требований. В одной из них, вроде, было все, что нужно, но она была shareware, а интерфейс был, мягко говоря, не очень удачный - у меня потребовало времени разобраться с ним и каким-то непонятным образом она произвела операцию поиска/замены над файлами, которые я не собирался трогать.

Наверное, я просто не проявил достаточно терпения, но, в конце концов, счел за лучшее написать такую утилиту самому. Потом, раз уж начал, добавил туда опций, которые не нужны для выполнения текущей задачи, но могут понадобиться позже - мне, или, может, кому другому.

Итак, Snr2, прошу любить и жаловать ( ссылка для скачивания, исходник и исполняемый файл ).

       snr2 [-tTemplateName] | [-hheaderName] | [-sSearchString -iInsertString]
            [-r[+|-]] [-c[+|-]] [-w[+|-]] [-f[+|-]] [-a[+|-]] [-v[+|-]] [-b[ext]] mask
    
    -tTemplateName - указывает имя текстового файла (TemplateName), в котором построчно перечислены разделенные пробелами пары найти/заменить;
    -hheaderName - указывает имя заголовочного файла (headerName) - подробнее об этом см. ниже;
    -sSearchString - фрагмент, который надо найти;
    -iInsertString - фрагмент, на который надо заменить найденную SearchString;
    -r - рекурсивный поиск во вложенных каталогах, по умолчанию выключен;
    -c - опция "Case sensitive", по умолчанию выключена;
    -w - опция "Whole words" - "Целые слова", по умолчанию включена, чтобы выключить, используйте -w-;
    -f - эта опция заменяет только имена функций (проверяет, следует ли за искомым словом круглая скобка), по умолчанию выключена;
    -a - автоматическая замена, по умолчанию включена. Если эта опция выключена при помощи -a-, то перед каждой заменой на экран выводится изменяемый фрагмент и вопрос: заменить или нет, на который вы должны ответить нажатием клавиши Enter или "y" (да), или "n" - нет;
    -v - более подробный журнал изменений, по умолчанию выключена;
    -b[ext]. По умолчанию старый файл остается без изменений и создается новый файл с добавленным расширением .new. Если вы задаете опцию -b, старый файл сохраняется с указанным вами расширением ( ext, если вы его не указали, то расширение по умолчанию - orig ), а новый занимает его место;
    mask - маска файлов, которые надо изменить, это может быть имя одного файла. Если вам надо использовать несколько масок, можно задать их через " ; ": *.prg;*.ch.

В командной строке надо указывать или -tTemplateName, или -hheaderName, или пару значений -sSearchString и -iInsertString. Если у вас одна пара значений для замены, например, SelectFile на hwg_SelectFile, то вы можете задать ее в командной строке:

       snr2 -sSelectFile -ihwg_SelectFile *.prg
    

Если таких пар несколько, то вам надо создать текстовый файл вот такого вида:

    SelectFile   hwg_SelectFile
    SaveFile     hwg_SaveFile
    Printersetup hwg_Printersetup
    
    и запустить snr2:
       snr2 -tshablon.txt *.prg
    
где shablon.txt - имя этого файла.

Специально для Harbour-программистов: в качестве шаблона можно использовать заголовочный ( *.h, *.ch ) файл, где строки что на что изменить задаются с помощью директивы #xtranslate:

    #xtranslate Selectfile([])          => hwg_Selectfile()
    

Таким образом, чтобы заменить вызовы функций на новые во всех ваших исходных файлах, написанных на [x]Harbour+HwGUI, надо сделать следующее:

       snr2 -hhwgcompat.ch -f -r *.prg
    
потому что именно в файле hwgcompat.ch собраны соответствущие директивы #xtranslate.

Еще пара слов о текстовых шаблонах, задаваемых опцией -t. Если вы меняете не названия функций, а произвольные строки с пробелами внутри, то соответствующую строку надо заключить в одинарные или двойные кавычки, например:

    "do while .t."   "DO WHILE TRUE"
    
Это же касается и опций командной строки -s, -i:
       snr2 -s"do while .t." -i"DO WHILE TRUE" *.prg
    

По окончании работы snr2 создается журнал snr2.log, в начале его перечислены пары найти/заменить и опции процесса, а затем список измененных файлов. Если была задана опция -v, то в журнал включаются фрагменты замененных строк.

Имеется и графический вариант этой утилиты - Fileagent