Bagaimana saya bisa memfilter file untuk baris yang berisi string di Sublime Text 2?

74

Saya ingin memfilter file yang saya edit di Sublime Text 2 untuk baris berisi string tertentu, jika mungkin termasuk ekspresi reguler.

Pertimbangkan file berikut:

foo bar
baz
qux
quuux baz

Ketika difilter untuk ba, hasilnya harus:

foo bar
baz
quuux baz

Bagaimana saya bisa melakukan itu?

Daniel Beck
sumber

Jawaban:

87

Sublime Text 2 adalah editor yang dapat diperluas dengan API Python . Anda dapat membuat perintah baru (disebut Plugin ) dan membuatnya tersedia dari UI.

Menambahkan plugin TextCommand pemfilteran dasar

Di Sublime Text 2, pilih Tools »New Plugin dan masukkan teks berikut:

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)

Simpan sebagai filter.pydi~/Library/Application Support/Sublime Text 2/Packages/User

Integrasi dengan UI

Untuk menambahkan plugin ini ke menu Edit , pilih Preferensi ... »Jelajahi Paket dan buka Userfolder. Jika file yang dipanggil Main.sublime-menutidak ada, buatlah. Tambahkan atau atur teks berikut ke file itu:

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

Ini akan menyisipkan filterpanggilan perintah (pada dasarnya, filterdiubah menjadi FilterCommand().run(…)untuk panggilan plugin dan Filter untuk label menu) tepat di bawah wrapperintah. Lihat langkah 11 di sini untuk penjelasan yang lebih terperinci mengapa demikian.

Untuk menetapkan pintasan keyboard, buka dan edit file Default (OSX).sublime-keymappada OS X, atau yang setara untuk sistem lain, dan masukkan yang berikut ini:

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

Ini akan menetapkan pintasan Funtuk perintah ini.


Untuk membuat perintah muncul di Palet Perintah , Anda perlu membuat file bernama Default.sublime-commands(atau mengedit yang sudah ada) di Userfolder. Sintaksnya mirip dengan file menu yang baru saja Anda edit:

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

Banyak entri (tertutup kurung keriting) harus dipisahkan dengan koma.

 Tangkapan layar perilaku dan integrasi UI

Perintah, seperti yang diterapkan, akan memfilter semua baris yang merupakan bagian dari pilihan (seluruh baris, bukan hanya bagian yang dipilih), atau, jika tidak ada pilihan, seluruh buffer, untuk substring yang dimasukkan ke bidang input ( default adalah - mungkin multi-line - clipboard) yang tidak berguna) setelah perintah dipicu. Dapat dengan mudah diperluas misalnya mendukung ekspresi reguler, atau hanya meninggalkan garis yang tidak cocok dengan ekspresi tertentu.

Item menu

Perintah dalam menu

Memerintahkan entri palet

Perintah dengan label berbeda di Commands Palette

Editor

Pengguna memasukkan teks untuk memfilter file dengan

Hasil setelah menjalankan perintah

Menambahkan dukungan untuk Ekspresi Reguler

Untuk menambahkan dukungan untuk ekspresi reguler, gunakan skrip dan snippet berikut sebagai gantinya:

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"
    }
]  

Perintah plugin kedua, Filter Menggunakan Ekspresi Reguler akan ditambahkan di bawah entri menu Filter .

Default.sublime-commands:

[
    { "caption": "Filter Lines in File", "command": "filter" },
    { "caption": "Filter Lines in File Using Regular Expression", "command": "filter_using_regular_expression" }
]
Daniel Beck
sumber
2
Tidakkah Anda ingin mempublikasikan ini sebagai paket suatu hari?
slhck
1
@ slhck Seseorang sudah melakukannya (dengan atribusi yang sesuai), lihat jawaban NovicePhysicist. Dari apa yang saya baca dalam kode, itu juga sedikit meningkat dari jawaban ini.
Daniel Beck
Keren, saya tidak memperhatikan itu!
slhck
Apa tema yang Anda miliki dengan SublimeText yang memberikan warna yang bagus? Atau hanya mengubah warna jendela?
pal4life
1
@ pal4life: Ini disebut Solarized (Cahaya) . Saya pikir Sublime Text bahkan mengirimnya. Saya mungkin telah menginstal alternatif, jadi warnanya mungkin tidak sama persis. Tangkapan layar ada di OS X, jadi dari situlah batas jendela dan bilah judul berasal.
Daniel Beck
83

Ada juga algoritma penyaringan garis orang miskin (atau apakah itu malas?):

  1. Pilih rangkaian minat
  2. Tekan Alt+ F3untuk masuk ke mode multi-kursor pada semua kejadian
  3. Tekan Control+ Luntuk memilih seluruh baris (pada setiap baris kursor)
  4. Salin-tempel pilihan ke buffer lain
Olof Bjarnason
sumber
2
Ini adalah solusi paling sederhana. Bravo!
gillytech
Terima kasih! Saya lebih suka tidak menginstal / mempelajari plugin lain sebanyak mungkin - Alt + F3 ada di memori otot saya sehingga solusi di atas sebenarnya tidak terlalu jauh bagi saya.
Olof Bjarnason
Anda dapat mengganti Langkah 3 dan 4 dengan satu langkah: Ctrl + L.
Andres Riofrio
1
Solusi sederhana yang bagus! Saya akan mengganti langkah 3 dari Ctrl-L ke Home, Shift-End Jadi tidak ada garis kosong antara kejadian.
jslap
4
Ini mengubah hidup saya menjadi lebih baik. Tidak akan ada yang sama lagi.
Shawson
49

Sekarang ada plugin untuk menyaring baris: https://github.com/davidpeckham/FilterLines
Memungkinkan penyaringan dan pelipat kode berdasarkan string atau ekspresi reguler.


Plugin Filter Teks Sublime oleh David Peckham

AllanLRH
sumber
4
Baru saja menginstal plugin ini - SEMPURNA untuk pekerjaan itu. Mengambil file yang sudah ada, memungkinkan Anda memasukkan frasa filter dan menempatkan hasilnya di tab baru.
Nick
4
Setuju, sampai sekarang saya hanya bermimpi memiliki fungsi semacam ini di editor teks saya.
Michael12345
1
Plugin ini sangat mengagumkan!
Devid
Datang ke sini karena seorang rekan kerja menyebutkan sesuatu tentang "Keep Lines" untuk emacs dan betapa berharganya itu. Bahkan tidak tahu saya membutuhkan plugin ini, benar-benar menyukainya!
brandon927
14

Anda dapat menggunakan kemampuan bawaan Sublime untuk melakukan ini dalam 3 hingga 7 stroke kunci (tidak termasuk regex yang akan dicocokkan).

Langkah 1: Multi-pilih semua garis yang cocok

Opsi 1: Untuk multi-pilih semua baris yang mengandung substring

  1. Pilih rangkaian minat.
  2. Tekan Alt+ F3untuk multi-pilih semua kejadian.
  3. Tekan Ctrl+ L(Perluas Seleksi ke Baris).

Opsi 2: Untuk multi-pilih semua baris yang cocok dengan regexp

  1. Tekan Ctrl+ Funtuk membuka laci Temukan.
  2. Pastikan pencocokan Ekspresi Reguler diaktifkan ( Alt+ Runtuk beralih).
  3. Ketikkan ekspresi reguler.
  4. Tekan Alt+ Enteruntuk multi-pilih semua pertandingan.
  5. Tekan Ctrl+ L(Perluas Seleksi ke Baris).

Langkah 2: Lakukan sesuatu dengan garis itu

Opsi 1: Untuk menghilangkan semua baris yang tidak dipilih

  1. Tekan Ctrl+ Cuntuk menyalin.
  2. Tekan Ctrl+ Auntuk memilih semua.
  3. Tekan Ctrl+ Vuntuk mengganti pilihan dengan garis yang cocok.

Opsi 2: Untuk menyingkirkan semua baris yang sedang dipilih

  1. Tekan Ctrl+ Shift+ K(Hapus Baris).

Opsi 3: Untuk mengekstrak baris yang dipilih ke file baru

  1. Tekan Ctrl+ Cuntuk menyalin.
  2. Tekan Ctrl+ Nuntuk membuka file baru.
  3. Tekan Ctrl+ Vuntuk menempel.
Andres Riofrio
sumber
Ini adalah daftar perintah yang luar biasa!
chustar
Super, tetapi apakah ada cara untuk menghapus garis kosong setelah menempel?
Sergey Senkov
1
@SergeySenkov Tentu! (1) Tekan Ctrl + F untuk membuka laci Cari. (2) Pastikan pencocokan Ekspresi Reguler diaktifkan (Alt + R untuk beralih). (3) Ketik "\ n \ n +" (cocok dengan dua atau lebih baris baru berturut-turut). (4) Tekan Alt + Enter untuk multi-pilih semua pertandingan. (5) Tekan Enter untuk mengganti semua pertandingan dengan satu baris baru.
Andres Riofrio