Здравствуйте, PSV100, Вы писали:
PSV>[...]
Дополню по поводу этих супер-сниппетов. Я немного поработал в HippoEdit, и заметил, что есть теоретические шансы что-то сделать в этом направлении. Вот картинка:
Я не разбирался подробно в правилах для синтаксиса, но эти Label и области синтаксиса у тебя отличные штуки. Система вызывает уважение. Вот сейчас курсор находится внутри метода generateParameterReifierCode и вверху показывается имя метода и его корректное определение, как полноценный заголовок синтаксической области (в моём понятии). Если я зайду курсором ниже во внутрь цикла "for", то система вычисляет новую вложенную область и корректно также показывает её заголовок, т.е. расписывает оператор for со всем содержимым в его скобках.
Так вот, можно дальше развить этот механизм, и реализовать правила для организации некоего режима для модификации/перехода по данным, по мотивам сниппетов. Назовём его условно "режим формы".
Например, для "for" уже как-то определено, что его "заголовочная область" находится внутри скобок. Пусть я нахожусь где-то внутри "for", клацнул "Ctrl-E Tab" — включился режим формы, я перелетел на начало цикла, на первое слово внутри скобок. Дальше я могу клацать tab/shift-tab и прыгать по словам внутри скобок, редактировать их, как в сниппетах. При этом, если есть одинаковые слова, например, переменные для цикла, при этом желательно учитывать, чтобы они находились не перед и не после точки (т.е. это не свойства/методы) — это как-то зависит от синтаксиса или как указали для синтаксической области, то сразу работает множественное изменение для этих одинаковых данных.
И таким же образом реализуется режим произвольной "формы ввода" — выделили любой блок (не при множественном выделении) и также внутри прыгаем по словам и можем их редактировать, включая одинаковые слова. Т.е. это нечто того режима, на который я давал когда-то ссылку как пример в IDE Lazarus-а (
здесь). Для выше примера с циклом "for" можно сказать, что это частный случай этого универсального режима, только мы явно не выделяем область внутри скобок оператора for.
Дальше. Пусть я переехал курсором выше цикла for, здесь уже область самой функции. Нажимаю "Ctrl-E Tab" — включаю режим формы и курсор прыгает на название метода, табом я прыгаю по именам параметров, типам и т.д. — т.е. внутри заголовка функции. Но при этом одинаковые слова также подсвечиваются и в соседней синтаксической области — JavaDoc-комментарии (имена параметров, сама функция). Т.е. нужно указать в файле-синтаксисе, что эти две области повязаны друг с другом (в этом случае расположены последовательно, так их можно отличать от других областей в тексте, ведь комментариев много, к разным функциям, и возможны другие варианты, когда области могут быть однозначно определены на уровне синтаксиса, например, разделы interface и implementation).
А когда я в самой области JavaDoc-комментария, то, соответственно, одинаковые слова подсвечиваются и в области функции. Но в самой области javadoc я прыгаю не по каждому слову, а по каким-то внутренним содержательным областям (их нужно определять в синтаксисе внутри javadoc): сразу выделяется вся область основного описательного комментария до аннотаций, при этом если я, скажем удалил текст, то внешний вид этого места должен быть корректно перестроен, т.е. должны учитываться отступы, звёздочки в начале строки и прочие префиксы и суффиксы (тут должен сработать другой режим, о котором была речь раньше). Дальше я прыгаю на само слово-аннотацию (т.е. на "@param"), дальше на значение этой аннотации и т.д.
А механизм сниппетов будет сам по себе, но похожий в принципах управления с режимом формы и логически с ним повязан (об этом ниже). Я тут глянул документацию по Sublime и заметил, что там эти сниппеты не очень развиты. Кроме самих переменных, которые могут быть как бы виртуальными (указывать на текущий выделенный текст, результат работы внешней программы и т.д.), слабовато развиты механизмы вычислений, есть какие-то преобразования через регэкспы. В Jedit как-то помощнее, можно писать полноценный код:
private ${2:Type} ${1:field};
/**
* Getter function for the field $1
*/
public $2 get${1=firstUp(s)}() {
return $1;
}
/**
* Setter function for the field $1
*/
public void set${1=firstUp(s)}($2 $1){
this.$1 = $1;
}
Т.е. писать код так: ${number=code}, где в параметре s содержится текст переменной, на которую ссылается эта позиция.
Также можно писать полноценные кодо-шаблоны:
<table>
<# for(i=0; i<=5; i++){ #>
<tr>
<# for(j=0; j<=5; j++){ #>
<td><#= i*j #></td>
<# } #>
</tr>
<# } #>
</table>
Но лично мне такая PHP-лапша не нравится. Для таких случаев удобны генераторы кода через прямое программирование, как, например, делает
Cog:
// This is my C++ file.
...
/*[[[cog
import cog
fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing']
for fn in fnames:
cog.outl("void %s();" % fn)
]]]*/
//[[[end]]]
...
Что превращается в:
// This is my C++ file.
...
/*[[[cog
import cog
fnames = ['DoSomething', 'DoAnotherThing', 'DoLastThing']
for fn in fnames:
cog.outl("void %s();" % fn)
]]]*/
void DoSomething();
void DoAnotherThing();
void DoLastThing();
//[[[end]]]
...
Т.е. лучше полностью самому печатать через out/outl, с нужным контролем всего форматирования, например, всех пробелов. Для сниппетов нужно просто указать код для выполнения, а такое форматирование через "[[...]]]" удобно для генераторов кода в самом тексте исходника. Я писал макрос — клацнул и сразу на месте обновился код (есть ещё возможность указывать контрольные суммы для проверок на предмет обнаружения ручного вмешательства в генерированный код, на сайте Cog есть примеры).
Но это не всё. Вот код:
CREATE TABLE inventory
(
id INT IDENTITY(1,1) PRIMARY KEY, -- это первичный ключ
product VARCHAR(50) UNIQUE, -- здесь уникальность
quantity INT,
price DECIMAL(18,2) -- ещё комментарий
);
В типовых этих сниппетах не хватает:
— повторяемость ввода. Вот здесь как-то можно задать подшаблон для ввода строки с информацией о поле таблицы. Нужен триггер, например, enter — поехали новый ввод (новая строка). Могут потребоваться и другие способы: ввели запятую при наборе параметра функции — перескочили на ввод нового параметра (повторяем подшаблон);
— инвариантность ввода. Вот если ввели в позиции слово PRIMARY, значит следующее будет KEY (автоматом добавили). Также нужно указание разных источников автокомплита, включая и элементарные списки (типа встроенные типы SQL);
— необязательность ввода. Пусть в полях ввода при работе сниппета светятся какие-то подсказки, например, влетел я в позицию для ввода, где может быть PRIMARY KEY, здесь может выделенным текстом светится: "PRIM UNIQ CHECK...". Как только я жму буквы — начинается ввод, не хочу — нажал tab и перелетел дальше или тут же на месте "перешли" к воду новой позиции (в зависимости от текущей ситуации с форматированием текста). Дальше, например, мне предлагают ввод комментария, но перед позицией поля ввода уже светится префикс "-- ", я ввожу текст или просто сразу enter — поехали заново подшаблон на новой строке, при этом, если я не ввел комментарий — префикс "-- " убрался;
— автовыравнивание текста. Причём нужны не только столбцы (типа этих резиновых табов), но и "объединение" виртуальных ячеек, разное выравнивание (влево, вправо, по центру, по ширине разбросать), короче говоря, виртуальные таблицы;
— и др. Имхо, направление ясно.
Здесь однозначно нужно делать простое и гибкое API для реализации "режима формы" и сниппетов, которое будет доступно и для текстовых макросов/скриптов. Тогда можно найти компромисс. Что-то дать возможность по простому задать декларативно в шаблонах (например, для виртуальных таблиц: $<tr> $<td> $</td> и т.д.), но "продвинутую" часть будет проще програмлять вручную. Тогда разработчик синтаксиса для языка сможет создать и типовой наборчик крутых сниппетов (кроме обычных), но и остальные, если захотят, тоже повозятся.
И этот же API нужен и для режима формы ввода для синтаксической области. Например, при редактировании заголовка функции, как в примере выше, можно программно корректировать сразу и область JavaDoc, скажем, вписывать там новые "@param ...". И это всё в рамках имеющегося парсера в редакторе, не на основе глобального AST для языка, которое в взрослых IDE.
Этот функционал можно связать с быстрыми переходами по мотивам вимператора, о котором говорили раньше. Например, при работе в форме ввода в такой синтаксической области CREATE TABLE (...) я чего-то клацнул, подсветились элементы внутри, ввёл пару букв — перелетел и сразу продолжаем форму ввода. Или при обычной работе я клацнул и включил режим быстрого перехода — перелетел в нужную синтаксическую область (можно подсвечивать только их начало) — и сразу поехал режим формы.
Также, если будет такой функционал, то упростится реализация таких плагинов, как для работы с
Zen Coding (имхо, очень вероятно, что тебя уже просили о нём подумать).
Вроде всё. Обязательно запиши себе, хотя бы из-за чувства уважения: у меня мозги плавились, пока писал. Потом выбросишь

.
А вот тот бред, по поводу того, что такой функционал реализовать только через сниппеты — можно выбросить. Я думал так: пусть мы находимся в том цикле "for" — клацнули "включить режим формы", редактор пытается подобрать шаблон по поводу "for", на основе их содержимого, как-то его запустить, с учётом того, что теперь позиции тех же переменных могут не соответствовать тому, что указано в шаблоне, но и т.д. Когда только как бы одна универсальная форма ввода для соответствующей синтаксической области — это вполне реально. И эти формы ввода вполне гармонично должны работать с независимыми сниппетами.
И небольшое замечание. Всё-таки несколько задёрганный индикатор текущей строки в редакторе, когда он прыгает вверх-вниз при прокрутке экрана (при его крайнем положении вверху/внизу и прокрутка через клавиатуру) — как-то портит солидность. Имхо, может быть, есть смысл как-то подправить цикл обработки сообщений, что ли. Но это не страшно.