Пишем макросы для TODO и FIXME в Sublime Text, или как немного кода позволяет сэкономить много времени +7


Великий Мастер бился с Хаосом. И чем крепче он бился, тем больше к нему приходило мыслей. Когда приходили мысли о толковом, он записывал их, предваряя магическим словом TODO. Мысли же о бестолковом он тоже записывал, но для таких мыслей у него было другое магическое слово — FIXME. И надо сказать, что от Начала Времён для победы над Хаосом не было более сильных заклинаний, чем эти два.



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


Что хотим получить


Нужно сразу определиться с тем, что мы хотим получить после вызова нашей команды вставки. Предполагаем, что курсор находится на какой-то строке кода, для которой мы хотим вставить TODO комментарий. Можно добавить комментарий в конец нашей строки. Но такое решение имеет два существенных недостатка. Во-первых, строка может оказаться слишком длинной, и, вставив комментарий, мы легко можем нарушить соглашение о максимальной длине строки. Даже если такого соглашения нет, работать с такой строкой будет неудобно. Во-вторых, если мы в процессе сборки приложения хотим использовать автоматический генератор файла TODO, содержащего список всех всех встретившихся ему в проекте TODO и FIXME комментариев со ссылками на файлы и номера строк в них, то может оказаться, что он предъявляет требование, чтобы эти комментарии находились в начале строк, как это делает todo-webpack-plugin, который использую я.


Итак, комментарий должен появиться над строкой, к которой мы хотим добавить TODO. То есть после запуска наша команда должна:


  1. перевести курсор в начало строки,
  2. вставить пустую строку,
  3. перевести курсор в начало этой новой строки,
  4. вставить символы, задающие комментарий для данного типа файла
    • // для JS, SCSS и др.
    • # для python и др.
    • <!-- для HTML, XML -->
    • И т.д. — где-то и ';' используется.
  5. вставить инструкцию TODO: и пробел после неё.

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


Пишем макрос


Для создания нашего инструмента логично воспользоваться средствами создания макросов, имеющимися в редакторе. Мы просто включим запись макроса, выполним некоторые действия в редакторе, остановим запись, сохраним её в файл и назначим горячие клавиши, по которым эта наша записанная последовательность действий — наш макрос — будет вновь запускаться, когда нам это потребуется.


Откроем какой-нибудь файл с кодом и поставим курсор на строку, для которой мы хотим (или делаем вид, что хотим, а на самом деле просто записываем макрос) добавить TODO. Включаем запись: Tools > Record Macro или сочетанием клавиш Ctrl+Alt+Q. Дале действуем по пунктам, рассмотренным выше.


  1. Home — переводим курсор в начало строки.
  2. Enter — вставляем пустую строку.
  3. Стрелка вверх — ставим курсор в начало этой пустой строки.
  4. Ctrl+/ — вставляем комментарий, пользуясь имеющейся в редакторе командой, которая корректно ставит комментарий в соответствии с содержимым кода.
  5. Вводим текст TODO: и пробел после него.

Останавливаем запись тем же сочетанием клавиш Ctrl+Alt+Q или Tools > Stop Recording Macro. Далее по Tools > Save Macro... открываем диалог записи макроса в файл. Зададим имя файла InsertTodo, оставив предложенное расширение .sublime-macro. Назначим хоткей. Для этого откроем Preferences > Key Bindings. Во вкладке Key Bindings — Default помещен список всех сочетаний клавиш по умолчанию, и команд, с ними связанных. Она нам нужна, чтобы найти незанятое сочетание клавиш, которое бы нас устроило. Было бы удобно использовать Ctrl+Shift+T, но этот хоткей в Linux перехватывается системой и открывает терминал. Сочетание Ctrl+Shift+D тоже занято — дублирует строку. Я остановился на Ctrl+Shift+= — оно оказалось свободно.


Вкладка “Key Bindings — User” служит для определения пользовательских сочетаний клавиш. Туда мы и пропишем наше новое сочетание:


[
    {
        "keys": ["Ctrl+shift+="],
        "command": "run_macro_file",
        "args": {"file": "Packages/User/InsertTodo.sublime-macro"}
    }
]

Это если файл был пустой. Если в нём уже что-то кроме скобок записано, то ставим там запятую после последней фигурной скобки, а со следующей строки добавляем наш объект:


[
    // Что-то...
    {
        // Последняя запись
    }, // Здесь нужна запятая
    {
        "keys": ["Ctrl+shift+="],
        "command": "run_macro_file",
        "args": {"file": "Packages/User/InsertTodo.sublime-macro"}
    }
]

Думаю, что смысл этой записи достаточно ясен. Ключ key хранит сочетание клавиш. command определяет команду, которая будет по этому сочетанию запущена. В нашем случае это run_macro_file, которая умеет запускать макросы. args хранит аргументы, передаваемые команде. В нашем случае передаётся путь к файлу нашего макроса.


Сохраняем, закрываем окошко с файлами настроек и испытываем то, что получилось. Убеждаемся, что всё корректно работает и в Python, и в JS и в HTML.


Что внутри


Теперь можно полюбопытствовать и заглянуть в сам файл InsertTodo.sublime-macro:


[
    {
        "args":
        {
            "extend": false,
            "to": "bol"
        },
        "command": "move_to"
    },
    {
        "args":
        {
            "characters": "\n"
        },
        "command": "insert"
    },
    {
        "args":
        {
            "by": "lines",
            "forward": false
        },
        "command": "move"
    },
    {
        "args":
        {
            "block": false
        },
        "command": "toggle_comment"
    },
    {
        "args":
        {
            "characters": "T"
        },
        "command": "insert"
    },
    {
        "args":
        {
            "characters": "O"
        },
        "command": "insert"
    },
    {
        "args":
        {
            "characters": "D"
        },
        "command": "insert"
    },
    {
        "args":
        {
            "characters": "O"
        },
        "command": "insert"
    },
    {
        "args":
        {
            "characters": ":"
        },
        "command": "insert"
    },
    {
        "args":
        {
            "characters": " "
        },
        "command": "insert"
    }
]

Ай — нехорошо! Каждый символ строки "TODO: " выводится своей командой. Исправим:


[
    {
        "args":
        {
            "extend": false,
            "to": "bol"
        },
        "command": "move_to"
    },
    {
        "args":
        {
            "characters": "\n"
        },
        "command": "insert"
    },
    {
        "args":
        {
            "by": "lines",
            "forward": false
        },
        "command": "move"
    },
    {
        "args":
        {
            "block": false
        },
        "command": "toggle_comment"
    },
    {
        "args":
        {
            "characters": "TODO: "
        },
        "command": "insert"
    }
]

Сохраняем и проверяем, что ничего не сломали. Всё работает.


А теперь FIXME


Соберём аналогичный инструмент для вставки FIXME. Для этого создадим файл InsertFixme.sublime-macro в том же каталоге, и скопируем в него содержимое из InsertTodo.sublime-macro, переправив в последней команде "TODO: " на "FIXME: ":


...
    {
        "args":
        {
            "characters": "FIXME: "
        },
        "command": "insert"
    }
]

Привязываем горячие клавиши. Сочетание Ctrl+Shift+- у меня оказалось свободным.


[
...
    {
        "keys": ["Ctrl+shift+="],
        "command": "run_macro_file",
        "args": {"file": "Packages/User/InsertTodo.sublime-macro"}
    },
    {
        "keys": ["Ctrl+shift+-"],
        "command": "run_macro_file",
        "args": {"file": "Packages/User/InsertFixme.sublime-macro"}
    }
]

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


Ссылки:






К сожалению, не доступен сервер mySQL