Как я могу отфильтровать файл по строкам, содержащим строку в Sublime Text 2?

Я хочу отфильтровать файл, который я редактирую, в Sublime Text 2, чтобы строки содержали определенную строку, если возможно, включая регулярные выражения.

Рассмотрим следующий файл:

foo bar
baz
qux
quuux baz

Когда фильтруется для ba, результат должен быть:

foo bar
baz
quuux baz

Как я могу это сделать?

4 ответа

Решение

Sublime Text 2 - это расширяемый редактор с Python API. Вы можете создавать новые команды (называемые плагинами) и делать их доступными из пользовательского интерфейса.

Добавление базового фильтра TextCommand

В Sublime Text 2 выберите Инструменты "Новый плагин и введите следующий текст:

import sublime, sublime_plugin

def filter(v, e, needle):
    # get non-empty selections
    regions = [s for s in v.sel() if not s.empty()]

    # if there's no non-empty selection, filter the whole document
    if len(regions) == 0:
        regions = [ sublime.Region(0, v.size()) ]

    for region in reversed(regions):
        lines = v.split_by_newlines(region)

        for line in reversed(lines):
            if not needle in v.substr(line):
                v.erase(e, v.full_line(line))

class FilterCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        def done(needle):
            e = self.view.begin_edit()
            filter(self.view, e, needle)
            self.view.end_edit(e)

        cb = sublime.get_clipboard()
        sublime.active_window().show_input_panel("Filter file for lines containing: ", cb, done, None, None)

Сохранить как filter.py в ~/Library/Application Support/Sublime Text 2/Packages/User

Интеграция с пользовательским интерфейсом

Чтобы добавить этот плагин в меню " Правка", выберите " Настройки"... "Просмотреть пакеты и откройте User папка. Если файл называется Main.sublime-menu не существует, создайте его. Добавьте или установите следующий текст в этот файл:

[
    {
        "id": "edit",
        "children":
        [
            {"id": "wrap"},
            { "command": "filter" }
        ]
    }
]

Это вставит filter вызов команды (по сути, filter превращается в FilterCommand().run(…) для вызова плагина и фильтра для метки меню) чуть ниже wrap команда. Смотрите шаг 11 здесь для более подробного объяснения, почему это так.

Чтобы назначить сочетание клавиш, откройте и отредактируйте файл Default (OSX).sublime-keymap на OS X или эквивалент для других систем и введите следующее:

[  
    {   
        "keys": ["ctrl+shift+f"], "command": "filter"
    }  
]  

Это назначит ярлык F для этой команды.


Чтобы команда появилась в палитре команд, вам нужно создать файл с именем Default.sublime-commands (или отредактируйте существующий) в User папка. Синтаксис похож на файл меню, который вы только что отредактировали:

[
    { "caption": "Filter Lines in File", "command": "filter" }
]

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

Скриншоты интеграции поведения и пользовательского интерфейса

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

Пункт меню

Команда в меню

Ввод палитры команд

Команда с другой меткой в ​​палитре команд

редактор

Пользователь вводит текст для фильтрации файла с

Результат после выполнения команды

Добавление поддержки регулярных выражений

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

filter.py:

import sublime, sublime_plugin, re

def matches(needle, haystack, is_re):
    if is_re:
        return re.match(needle, haystack)
    else:
        return (needle in haystack)

def filter(v, e, needle, is_re = False):
    # get non-empty selections
    regions = [s for s in v.sel() if not s.empty()]

    # if there's no non-empty selection, filter the whole document
    if len(regions) == 0:
        regions = [ sublime.Region(0, v.size()) ]

    for region in reversed(regions):
        lines = v.split_by_newlines(region)

        for line in reversed(lines):

            if not matches(needle, v.substr(line), is_re):
                v.erase(e, v.full_line(line))

class FilterCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        def done(needle):
            e = self.view.begin_edit()
            filter(self.view, e, needle)
            self.view.end_edit(e)

        cb = sublime.get_clipboard()
        sublime.active_window().show_input_panel("Filter file for lines containing: ", cb, done, None, None)

class FilterUsingRegularExpressionCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        def done(needle):
            e = self.view.begin_edit()
            filter(self.view, e, needle, True)
            self.view.end_edit(e)

        cb = sublime.get_clipboard()
        sublime.active_window().show_input_panel("Filter file for lines matching: ", cb, done, None, None)

Main.sublime-menu:

[
    {
        "id": "edit",
        "children":
        [
            {"id": "wrap"},
            { "command": "filter" },
            { "command": "filter_using_regular_expression" }
        ]
    }
]

Default (OSX).sublime-keymap:

[  
    {   
        "keys": ["ctrl+shift+f"], "command": "filter"
    },
    {
        "keys": ["ctrl+shift+option+f"], "command": "filter_using_regular_expression"
    }
]  

Вторая команда плагина, Filter Using Regular Expression, будет добавлена ​​ниже пункта меню Filter.

Default.sublime-commands:

[
    { "caption": "Filter Lines in File", "command": "filter" },
    { "caption": "Filter Lines in File Using Regular Expression", "command": "filter_using_regular_expression" }
]

Существует также алгоритм фильтрации строк для бедного человека (или он ленивый?):

  1. Выберите интересующую строку
  2. Нажмите Alt + F3, чтобы перейти в режим нескольких курсоров во всех случаях
  3. Нажмите Control + L, чтобы выделить всю строку (на каждой строке курсора)
  4. Копировать-вставить выделение в другой буфер

Теперь есть плагин для фильтрации строк: https://github.com/davidpeckham/FilterLines
Это позволяет фильтровать и сворачивать код на основе строк или регулярных выражений.


Плагин Sublime Text Filter от Дэвида Пекхэма

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

Шаг 1: мульти-выбрать все совпадающие строки

Вариант 1: чтобы выбрать несколько строк, содержащих подстроку

  1. Выберите интересующую строку.
  2. Нажмите Alt + F3, чтобы выбрать несколько событий.
  3. Нажмите Ctrl + L (Расширить выделение до строки).

Вариант 2: чтобы выбрать несколько строк, соответствующих регулярному выражению

  1. Нажмите Ctrl + F, чтобы открыть ящик поиска.
  2. Убедитесь, что сопоставление регулярных выражений включено (Alt + R для переключения).
  3. Введите регулярное выражение.
  4. Нажмите Alt + Enter, чтобы выбрать все совпадения.
  5. Нажмите Ctrl + L (Расширить выделение до строки).

Шаг 2: Сделайте что-нибудь с этими строками

Вариант 1: избавиться от всех не выделенных строк

  1. Нажмите Ctrl + C, чтобы скопировать.
  2. Нажмите Ctrl + A, чтобы выбрать все.
  3. Нажмите Ctrl + V, чтобы заменить выделение соответствующими линиями.

Вариант 2: избавиться от всех выбранных линий

  1. Нажмите Ctrl + Shift + K (Удалить строку).

Вариант 3: Извлечь выделенные строки в новый файл

  1. Нажмите Ctrl + C, чтобы скопировать.
  2. Нажмите Ctrl + N, чтобы открыть новый файл.
  3. Нажмите Ctrl + V, чтобы вставить.
Другие вопросы по тегам