2017-01-15 12 views
11

У меня есть следующие строки в Default (Windows).sublime-keymap файле подключаемого модуля:Trigger действия для каждого буквенно-цифрового нажатия клавиши

... 
{ "keys": ["ctrl+shift+a"], "command": "table_editor_align", "context": 
    [ 
     { "key": "setting.enable_table_editor", "operator": "equal", "operand": true, "match_all": true }, 
     { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, 
     { "key": "following_text", "operator": "regex_contains", "operand": "$", "match_all": true } 
    ] 
}, 
... 

Вместо запускающего эту команду только при Ctrl + сдвиг + , я бы как запускать эту команду после каждого буквенно-цифрового нажатия (AZ, az, 0-9, и почему бы и не акценты é, à, ç и т. д. т.е. все символы, которые мы используем во время записи)?

"keys": ["[a-zA-Z0-9_]"] 

, похоже, не работает.

Примечание: плагин в настоящее время является подклассом sublime_plugin.TextCommand, и я считаю, что это необходимо для его работы. Плагин Я пытаюсь изменить это https://github.com/vkocubinsky/SublimeTableEditor, я хотел бы, что автоматическое повторное выравнивание производится автоматически после каждого нажатия клавиши, а не после каждой клавиши CTRL + SHIFT + A, как здесь:

enter image description here

+0

Вам было бы намного лучше написать подкласс подкастов ['sublime_plugin.EventListener'] (http://www.sublimetext.com/docs/3/api_reference.html#sublime_plugin.EventListener) и использовать его' on_modified() '. – MattDMo

+0

@MattDMo плагин в настоящее время является подклассом sublime_plugin.TextCommand, и я считаю, что это необходимо для его работы. Плагин, который я пытаюсь изменить, - https://github.com/vkocubinsky/SublimeTableEditor. – Basj

ответ

7

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


[править] Существует на самом деле способ сделать это; Я добавил больше информации к концу моего ответа [/ править]


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

Один из способов сделать это, как предложено MattDMO, использовать обработчик on_modified для отслеживания изменения буфера, а затем запускать перегруппировку таким образом.

Пример плагин, который может сделать что-то вроде этого является следующее:

import sublime 
import sublime_plugin 
import re 

class TableFormatEventListener(sublime_plugin.EventListener): 
    def __init__(self): 
     self._views = dict() 
     self.regex = re.compile(r"\s*\|") 

    def on_modified(self, view): 
     # Only for views with table editing enabled that are not already being 
     # modified 
     if (view.settings().get("enable_table_editor", False) and 
       self._views.get(view.id(), False) is False): 

      for s in view.sel(): 
       line = view.substr(view.line(s.begin())) 
       prior = view.substr(s.begin() - 1) if s.begin() > 0 else "" 

       # Only if all cursors are inside of a table row and the 
       # character prior to the cursor is not a space 
       if self.regex.match(line) is None or prior == " ": 
        return 

      # Perform the realignment 
      self._views[view.id()] = True 
      view.run_command("table_editor_align") 
      self._views[view.id()] = False 

    def on_text_command(self, view, cmd, args): 
     # Don't trigger reformatting while an undo is happening 
     if cmd == "undo": 
      self._views[view.id()] = True 

    def on_post_text_command(self, view, cmd, args): 
     # Undo is complete; resume reformat handling 
     if cmd == "undo": 
      self._views[view.id()] = False 

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

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

Кроме того, также проверяется, был ли добавлен последний добавленный символ. Это связано с тем, что переформатирование, по-видимому, устраняет конечные пробелы, что фактически блокирует вас от возможности ввода пространства в любом месте таблицы.

Предполагая, что все курсоры находятся в строках таблицы и не просто вставляют пробел, команда для выравнивания таблицы выполняется в текущем представлении.

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

Чтобы прекратить это, мы сохраняем дорожку представлений, которые должны были проигнорировать событие on_modified, добавив текущее представление в список до изменения таблицы, а затем удалив его, как только мы закончим.

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

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

Теперь у вас немного рассол, потому что вы не можете отменить изменение; когда вы один раз отжимаете отменить, он отменяет перегруппировку, но при этом он модифицирует буфер, который вызывает повторную замену.

Чтобы решить эту проблему, прослушиватель событий также прослушивает, когда произойдет команда undo, и убедитесь, что, пока происходит отмена, обработчик модификации не будет перестраивать таблицу.

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

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


[править]

Как это происходит, то на самом деле это способ сделать что-то подобное тому, что вы изначально просили. Можно назначить привязку клавиш, которая будет запускаться для любого вставленного символа, хотя вам все равно нужно немного кода плагина для склеивания, чтобы связать все вместе (а также несколько вопросов удобства использования относятся к тому, как плагин таблицы выполняет переформатирование).

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

import sublime 
import sublime_plugin 

class TextAndAlignTableCommand(sublime_plugin.TextCommand): 
    def run(self, edit, character): 
     self.view.run_command("insert", {"characters": character}) 
     if character != " ": 
      self.view.run_command("table_editor_align") 

Это определяет команду, которая принимает один аргумент character, который будет вставить в буфер путь характер, как правило, вводятся. Затем, если символ не является пространством, он также вызывает команду для выравнивания таблицы.

При этом в месте, ключ привязки для создания является:

{ "keys": ["<character>"], "command": "text_and_align_table", "context": 
    [ 
     { "key": "setting.enable_table_editor", "operator": "equal", "operand": true, "match_all": true }, 
     { "key": "preceding_text", "operator": "regex_contains", "operand": "^\\s*\\|", "match_all": true }, 
     { "key": "following_text", "operator": "regex_match", "operand": "\\s*\\|.*$", "match_all": true } 
    ] 
}, 

В основном это ключ привязки, который вы упомянули выше (который по умолчанию для базовой таблицы плагин для запуска переформатировать) с некоторыми небольшие изменения.

Во-первых, ключ привязан к ключу <character>, что делает его потенциально триггером для любого символа, который иначе был бы вставлен в буфер.

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

В-третьих, контекст following_text изменен таким образом, что он запускается только тогда, когда он находится в конце столбца в таблице, так что можно вставить текст в середину столбца, не указав позицию курсора, конец столбца.

При привязке этого способа привязка будет вызываться для любого отдельного символа и вызовет команду, предоставленную с аргументом, который сообщает вам, что это за символ. Сама привязка не может иметь на ней модификатора (например, ctrl, shift и т. Д.), Но персонаж, который вы получаете, является тем, который в противном случае был бы напечатан.

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

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

С другой стороны, по-прежнему невозможно иметь пробелы в конце значения столбца (после переформатирования), потому что tableformat хочет удалить их. Чтобы не допустить этого, базовый плагин должен быть изменен, чтобы этого не делать, но похоже, что он несколько скомпрометировал форматирование таблицы.

+0

Ну, код выше будет иметь нужный эффект и перестроить таблицу на каждом редактировании. Было бы довольно легко создать «TextCommand», который вставлял бы символ, а затем перестраивал бы таблицу, но тогда вам нужно было бы создать привязку ключа для ее выполнения для каждого символа, который вы, возможно, захотите ввести в таблицу. – OdatNurd

+0

Большое спасибо @OdatNurd, он работает :) Только проблема: отмена не работает ... (вы упомянули такие случаи с краем в своем развитии), вы пробовали это с помощью плагина? Может быть, это просто что-то маленькое. Есть идеи? – Basj

+0

Любая операция, которая модифицирует буфер при активном подключаемом модуле, принимает как минимум два действия (один для вставки текста и один для переформатирования таблицы), поэтому вам может потребоваться несколько раз отменить несколько раз, чтобы вернуться туда, где вы ожидаете это к. Возможно, больше, если операция переформатирования делает более одного редактирования, но я не знаю, было ли это то, что она делает или нет (это не было в моих тестах во всяком случае) – OdatNurd