Comment filtrer un fichier pour les lignes contenant une chaîne dans Sublime Text 2?

74

Je souhaite filtrer un fichier que je suis en train de modifier dans Sublime Text 2, car les lignes contiennent une certaine chaîne, y compris, si possible, des expressions régulières.

Considérez le fichier suivant:

foo bar
baz
qux
quuux baz

Une fois filtré ba, le résultat devrait être:

foo bar
baz
quuux baz

Comment puis je faire ça?

Daniel Beck
la source

Réponses:

87

Sublime Text 2 est un éditeur extensible avec une API Python . Vous pouvez créer de nouvelles commandes (appelées Plugins ) et les rendre disponibles à partir de l'interface utilisateur.

Ajout du plugin TextCommand de filtrage de base

Dans Sublime Text 2, sélectionnez Outils »Nouveau plug-in et entrez le texte suivant:

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)

Enregistrer comme filter.pydans~/Library/Application Support/Sublime Text 2/Packages/User

Intégration avec l'interface utilisateur

Pour ajouter ce plugin au menu Edition , sélectionnez Préférences… »Parcourir les packages et ouvrez le Userdossier. Si un fichier appelé Main.sublime-menun'existe pas, créez-le. Ajoutez ou définissez le texte suivant dans ce fichier:

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

Cela insérera l' filterappel de commande (essentiellement filtertransformé en FilterCommand().run(…)appel de plugin et Filtre pour le libellé du menu) juste en dessous de la wrapcommande. Voir l' étape 11 ici pour une explication plus détaillée pourquoi.

Pour attribuer un raccourci clavier, ouvrez et modifiez le fichier Default (OSX).sublime-keymapsous OS X, ou l’équivalent pour d’autres systèmes, puis entrez les informations suivantes:

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

Cela assignera le raccourci Fà cette commande.


Pour que la commande apparaisse dans la palette Commandes , vous devez créer un fichier nommé Default.sublime-commands(ou modifier un fichier existant) dans le Userdossier. La syntaxe est similaire à celle du fichier de menu que vous venez de modifier:

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

Les entrées multiples (entre accolades) doivent être séparées par des virgules.

 Captures d'écran de l'intégration du comportement et de l'interface utilisateur

La commande, telle qu’elle est mise en œuvre, filtrera toutes les lignes qui font partie d’une sélection (les lignes entières, pas seulement les parties sélectionnées) ou, s’il n’ya pas de sélection, la totalité du tampon pour une sous-chaîne entrée dans le champ d’entrée ( La valeur par défaut est le presse-papiers éventuellement éventuellement multi-lignes) une fois la commande déclenchée. Il peut facilement être étendu pour prendre en charge, par exemple, les expressions régulières ou ne laisser que des lignes ne correspondant pas à une expression donnée.

Élément du menu

Commande dans le menu

Entrée de la palette de commandes

Commande avec une étiquette différente dans la palette de commandes

Éditeur

Utilisateur saisissant du texte pour filtrer le fichier avec

Résultat après exécution de la commande

Ajout du support pour les expressions régulières

Pour ajouter la prise en charge des expressions régulières, utilisez plutôt les scripts et extraits suivants:

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

Une deuxième commande de plug-in, Filtre utilisant une expression régulière, sera ajoutée sous l' entrée de menu Filtre .

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
la source
2
Ne voulez-vous pas publier cela comme un paquet un jour?
Slhck
1
@slhck Quelqu'un l'a déjà fait (avec l'attribution appropriée), voir la réponse de NovicePhysicist. D'après ce que j'ai lu dans le code, cette réponse a également été améliorée.
Daniel Beck
Cool, je n'ai pas remarqué ça!
Slhck
Quel est le thème que vous avez avec le SublimeText qui donne ces belles couleurs? Ou s'agit-il simplement de changer la couleur de la fenêtre?
pal4life
1
@ pal4life: Cela s'appelle Solarized (Light) . Je pense que Sublime Text est même livré avec. J'aurais peut-être installé une alternative cependant, donc les couleurs pourraient ne pas correspondre exactement. Les captures d’écran sont sur OS X, c’est de là que viennent la bordure de la fenêtre et la barre de titre.
Daniel Beck
83

Il existe également un algorithme de filtrage de lignes pour les pauvres (ou est-il paresseux?):

  1. Sélectionnez une chaîne d'intérêt
  2. Appuyez sur Alt+ F3pour passer en mode multi-curseur à toutes les occurrences
  3. Appuyez sur Control+ Lpour sélectionner la ligne entière (sur chaque ligne du curseur)
  4. Copier-coller la sélection dans un autre tampon
Olof Bjarnason
la source
2
C'est à peu près la solution la plus simple. Bravo!
gillytech
Je vous remercie! Je préfère ne pas avoir à installer / apprendre un autre plugin pour autant que possible - Alt + F3 est dans ma mémoire musculaire, donc la solution ci-dessus n'est en fait pas si loin pour moi.
Olof Bjarnason
Vous pouvez remplacer les étapes 3 et 4 par une seule étape: Ctrl + L.
Andres Riofrio
1
Belle solution simple! Je voudrais remplacer l'étape 3 de Ctrl-L vers Home, Shift-End afin qu'il n'y ait pas de lignes vides entre les occurrences.
Jslap
4
Cela a changé ma vie pour le mieux. Rien ne sera plus jamais pareil.
Shawson le
49

Il existe maintenant un plugin pour filtrer les lignes: https://github.com/davidpeckham/FilterLines
Il permet le filtrage et le repliement du code en fonction de chaînes ou d'expressions régulières.


Sublime Text Filter Plugin de David Peckham

AllanLRH
la source
4
Je viens d'installer ce plugin - PARFAIT pour le travail. Prend un fichier existant, vous permet de saisir une phrase de filtrage et de placer les résultats dans un nouvel onglet.
Nick
4
D'accord, je n'avais jusqu'à présent jamais rêvé d'intégrer ce type de fonctionnalité dans mon éditeur de texte.
Michael12345
1
Ce plugin est vraiment génial!
Devid
Nous sommes venus ici parce qu'un collègue a parlé de "Keep Lines" pour emacs et de son utilité. Je ne savais même pas que j'avais besoin de ce plugin, je l'adore!
brandon927
14

Vous pouvez utiliser les fonctionnalités intégrées de Sublime pour le faire en 3 à 7 frappes de touches (sans inclure l'expression régulière à faire correspondre).

Étape 1: Sélectionner plusieurs fois toutes les lignes correspondantes

Option 1: pour sélectionner plusieurs fois toutes les lignes contenant une sous-chaîne

  1. Sélectionnez la chaîne d'intérêt.
  2. Appuyez sur Alt+ F3pour sélectionner plusieurs fois toutes les occurrences.
  3. Appuyez sur Ctrl+ L(élargir la sélection à la ligne).

Option 2: Pour sélectionner plusieurs fois toutes les lignes correspondant à une expression rationnelle

  1. Appuyez sur Ctrl+ Fpour ouvrir le tiroir Trouver.
  2. Assurez-vous que la correspondance des expressions régulières est activée ( Alt+ Rpour basculer).
  3. Tapez l'expression régulière.
  4. Appuyez sur Alt+ Enterpour sélectionner plusieurs fois toutes les correspondances.
  5. Appuyez sur Ctrl+ L(élargir la sélection à la ligne).

Étape 2: Faites quelque chose avec ces lignes

Option 1: supprimer toutes les lignes non sélectionnées

  1. Appuyez sur Ctrl+ Cpour copier.
  2. Appuyez sur Ctrl+ Apour tout sélectionner.
  3. Appuyez sur Ctrl+ Vpour remplacer la sélection par les lignes correspondantes.

Option 2: Pour se débarrasser de toutes les lignes qui sont sélectionnées

  1. Appuyez sur Ctrl+ Shift+ K(Supprimer la ligne).

Option 3: extraire les lignes sélectionnées dans un nouveau fichier

  1. Appuyez sur Ctrl+ Cpour copier.
  2. Appuyez sur Ctrl+ Npour ouvrir un nouveau fichier.
  3. Appuyez sur Ctrl+ Vpour coller.
Andres Riofrio
la source
C'est une excellente liste de commandes!
Chustar
Super, mais y a-t-il moyen de supprimer les lignes vides après le collage?
Sergey Senkov
1
@SergeySenkov Bien sûr! (1) Appuyez sur Ctrl + F pour ouvrir le tiroir Rechercher. (2) Assurez-vous que la correspondance des expressions régulières est activée (Alt + R pour basculer). (3) Tapez "\ n \ n +" (correspond à deux nouvelles lignes consécutives ou plus). (4) Appuyez sur Alt + Entrée pour sélectionner plusieurs fois toutes les correspondances. (5) Appuyez sur Entrée pour remplacer toutes les correspondances avec une seule nouvelle ligne.
Andres Riofrio