LINUX.ORG.RU

Трудности при написание сниппетов с Yasnippet


0

2

Поставил перед собой такую задачу: написать простой сниппет для if для лиспов.

Я хочу добиться поведения в котором в случае короткой записи if укладывался бы в одну строку, а в случае длинной использовался перенос строки. Что то вроде:

(if (> a b) a b)
(if (long-condition)
    (long-then-section)
  (long-else-section))

А еще в if может отсутствовать else-часть и в этом случае не должно быть одиночной скобки на строке.

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

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

(if ${1:$$(код парсинга выражения)) 
я не могу т.к. надо сохранить возможность навигации при помощи yas/next-field и yas/prev-field.

Написать

(if ${4:$1 $2 $3})
тоже нельзя т.к. при вызове yas/next-field когда курсор будет на тройке, он перейдет на четверку, а надо, чтобы переходил в конец этой конструкции.

Вторая проблема в выравнивании. Для примера(только для примера!) я пишу такой сниппет:

(if $1${1:$(if (> (length yas/text) 10) «\n\t» "")} $2${2:$(if (> (length yas/text) 10) «\n\t» "")} $3) $0

С короткой записью он работает, с длинной выходит вот так:

(if (long-condition) 
	(then-section) 
	(else-section))
а должно вот так:
(if (long-condition) 
    (then-section) 
  (else-section))
Что может помочь в данной ситуации? Куда посмотреть можно? Какие есть альтернативы?

Сразу замечу, я срашиваю не только для if'а, просто на его примере...

Первая проблема - мне нужно узнать длинну всей конструкции.

Тебе не нужна длина всей конструкции, тебе надо сканировать наличие переноса строки в condition-секции:

# -*- mode: snippet -*-
# name: if
# key: iff
# --
(if (${1:condition}) ${1:$(when (string-match "[\n]" yas/text) "\n\t")}(${2:body}))
$0

Остальное пока не распарсил.

Вопрос для Development-a, неудачный форум выбрал.

Reaper ★★
()
Ответ на: комментарий от Reaper

Вернее, не when, a cond:

# -*- mode: snippet -*-
# name: if
# key: iff
# --
(if (${1:condition}) ${1:$(cond ((string-match "[\n]" yas/text) 
    (progn (indent-region (region-beginning) (region-end)) "\n\t"))
    (t ""))}(${2:body}))
$0
Reaper ★★
()
Ответ на: комментарий от Reaper

Вопрос для Development-a, неудачный форум выбрал.

Вот, блин... ~~" как бы ее теперь перенести...

То, что Вы написали, у меня не работает... :( Проблема в «\n\t». Вот это `\t` выводит именно табуляцию. т.е. не происходит выравнивания... Т.е. вместо:

(if (long) 
    (then) 
  (else))
выходит
(if (long) 
	(then) 
	(else))

Тебе не нужна длина всей конструкции, тебе надо сканировать наличие переноса строки в condition-секции.

Остальное пока не распарсил.

Попробую объяснить проще. Есть некоторое количество формальных паттернов форматирования кода, которыми я пользуюсь с целью улучшения читабельности, наглядности, красивости и пр. Впрочем как и многие другие...

Пара примеров:

1. Выравнивание «значений» при объявлении переменных:

(let ((foo      (gensym))
      (long-foo (gensym)))
      ...)
вместо
(let ((foo (gensym))
      (long-foo (gensym)))
      ...)
2. Ряд конструкции вроде if'a подчиняется стандартным правилам, например каждая секция if-a(condition, then и else) должна начинаться с новой строки, если:

  • хотя бы в одной из секций присутствует перевод строки.
  • хотя бы одна из секций начинается с новой строки.
  • если длинна всего if'a в символах больше какого то значения.

Сразу отвечу на вопрос, зачем это нужно. Это не для сокращения ввода, а для того, чтобы голова оставалась свободной от выравнивания и занята только решаемой задачей. Для того же служит, например, слепая печать, которая освобождает голову и зрительный анализатор.

arte-at-marte
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.