VIM - Este não é apenas um editor, é uma integração com todo o seu ambiente de trabalho

Por que o Vim / Neovim é particularmente bom? O fato de seu kit de ferramentas não ser apenas um editor (que é extensível com plug-ins e possui uma funcionalidade básica rica e muito flexível no campo da personalização), mas também todo o seu ambiente de trabalho , com todo o kit de ferramentas unix-way incluído no gnu / coreutils e não somente. Sem sair do editor, você pode pegar qualquer programa ou intérprete e usá-lo diretamente no editor.


Prefácio


Este post foi escrito às pressas para um círculo particular de pessoas, mas decidi que é bem possível publicá-lo no Habr. Para alguns, isso pode se tornar uma inspiração, alguém ajudará a entender melhor a filosofia do Vim e alguém fará alguns truques para si. Por via das dúvidas, farei uma reserva de que não devo esperar que comece a provar algo para alguém nos comentários, por exemplo, para convencê-lo de que você definitivamente precisa abandonar seu IDE gordo e começar a usar o Vim, não estou nem um pouco interessado nisso.


Para negócios


Aqui, por exemplo, pegue um trecho de código (da configuração do projeto Haskell), uma lista de dependências de pacotes (exemplo no vácuo):


build-depends: X11 , base , directory , extra , GLFW-b , safe , aeson , containers , data-default , text , process , time , dbus 

O que nós queremos?


  1. Classificar dependências em ordem alfabética
  2. Classificar sem GLFW-b entre maiúsculas e minúsculas ( X11 e GLFW-b não devem subir acima de tudo)
  3. Restaurar vírgulas ( aeson vai para o topo e não deve mais ter uma vírgula à esquerda, mas X11 deve ter uma vírgula à esquerda)
  4. Restaure o recuo (para que você também possa obter o comando do histórico e reutilizá-lo em outra configuração com um nível de aninhamento diferente, ou até vincular o comando hotkey na configuração do Vim)

Solução


Antes de tudo, selecione (destacando visualmente) a lista de dependências, exceto a primeira linha de dependências de build-depends . Obviamente, basta pressionar V (modo visual com seleção linha a linha) e selecionar as linhas necessárias através das setas jk ou para cima e para baixo. No meu caso, faço isso com um aceno da mão usando uma tecla de atalho personalizada para o modo visual:


 xn iz <esc>[zV]z 

Por exemplo, estando no meio da lista de dependências, basta pressionar viz e todas as dependências são destacadas, porque a dobra inteira é destacada, que por sua vez é o bloco de aninhamento atual (desde que defini o foldmethod como indent ). Mas você também pode digitar manualmente [zV]z sequencialmente sem uma tecla de atalho personalizada ( [z salta para o início da dobra, a ]z para o final), mas como para mim, essa operação é frequentemente usada, então a viz para viz - não há modificadores como uma mudança e ela é comprimida em reflexos em um instante (o analógico padrão mais próximo é vip para selecionar um bloco para as linhas vazias mais próximas).


Em seguida, pressione : (dois pontos) para entrar no modo de comando para executar um comando relativo ao destaque visual atual. De fato, o modo de comando usual, mas com marcadores de seleção adicionados imediatamente, ou seja, terá a seguinte aparência :'<,'> onde '<,'> é o intervalo de seleção, onde '< é a primeira linha da seleção visual e '> é a última.


Depois que clicarmos ! (ponto de exclamação) no teclado, isso significa que tudo o que vai além é um comando shell / bash (dependendo das configurações). Será parecido com :'<,'>! . De fato, após destacar, você pode clicar imediatamente ! e obtenha o mesmo resultado - :'<,'>! .


Esta operação redirecionará as linhas destacadas para o comando STDIN e substituirá as linhas destacadas pelo escape STDOUT deste comando. Por exemplo, você pode usar o comando de sort , exclusivamente para verificação, o resultado não é o que precisamos - '<,'>!sort e pressione Enter , obtemos:


  build-depends: , aeson , base , containers , data-default , dbus , directory , extra , GLFW-b , process , safe , text , time X11 

Moda com coreutils e torre geral


Restaure a seleção anterior (você pode pressionar gv para restaurar a última seleção) e pressionar ! e depois a seta para cima - isso restaurará o último comando do histórico; portanto, não precisamos escrever novamente; apenas extraímos o comando anterior do histórico e o alteramos. Para editar com mais facilidade o comando, você pode pressionar Ctrl + f - isso abrirá adicionalmente. uma janela com edição padrão normal do comando, com todos os recursos do Vim, a propósito, todas as equipes anteriores da história estarão visíveis lá como linhas separadas, que também podem ser selecionadas, editadas e executadas.


Qual é a coisa certa a fazer - você pode pensar em uma descoberta, o que quero dizer é: primeiro removemos as vírgulas, as separamos sem elas (sem distinção entre maiúsculas e minúsculas), depois retornamos as vírgulas, exceto a primeira linha.


Primeiro, removemos as vírgulas (e a primeira linha tem um recuo extra para que todas as linhas tenham o mesmo recuo) usando o comando sed com uma expressão regular ( [, ] - uma vírgula ou espaço e, em seguida, outro espaço, \(\w\) escapou entre colchetes para destacar bloco de substituição, para que fique disponível como \1 , \w é o primeiro caractere alfabético; na substituição, restauraremos o caractere alfabético substituindo \1 ):


 :'<,'>!sed 's/[, ] \(\w\)/\1/' 

Temos o seguinte:


  build-depends: X11 base directory extra GLFW-b safe aeson containers data-default text process time dbus 

Em seguida, canalizamos (através do símbolo | é um recurso do bash) o comando sort sort , passando a -f para diferenciar maiúsculas de minúsculas:


 :'<,'>!sed 's/[, ] \(\w\)/\1/' | sort -f 

Temos:


  build-depends: aeson base containers data-default dbus directory extra GLFW-b process safe text time X11 

Quase pronto! Resta apenas adicionar vírgulas e a primeira linha - alguns espaços. Usamos o mesmo sed ; na sintaxe de suas operações, você pode especificar cadeias e intervalos de cadeias (como no próprio Vim, a sintaxe é a mesma, bem ou quase a mesma). O prefixo 1 significa a primeira linha, 2,$ significa o intervalo da 2ª linha até o final ( $ , como ^ significa o início do arquivo, por analogia com os mesmos caracteres em expressões regulares que significam o fim e o início da linha). Usaremos \w para pular o recuo e selecionar imediatamente o primeiro caractere alfabético: 1s/\w/ &/ - aqui substituímos a primeira linha, restauramos o primeiro caractere alfabético por & (semelhante a \1 , somente & significa tudo sob todo o regex, enquanto \1 significa o primeiro bloco entre parênteses), adicionando alguns espaços à sua frente. Para as linhas restantes, em vez de dois espaços, adicione uma vírgula + espaço seguido por: 2,$s/\w/, &/ , todo o comando será assim: sed -e '1s/\w/ &/' -e '2,$s/\w/, &/' , - -e usamos para separar duas operações uma da outra. No Vim, toda a operação será semelhante a:


 :'<,'>!sed 's/[, ] \([^, ]\)/\1/' | sort -f | sed -e '1s/\w/ &/' -e '2,$s/\w/, &/' 

Nós aplicamos e obtemos:


  build-depends: aeson , base , containers , data-default , dbus , directory , extra , GLFW-b , process , safe , text , time , X11 

Feito! Não é mais necessário escrever uma segunda vez, basta digitar os primeiros caracteres, por exemplo: :'<,'>!se (na verdade, você só precisa pressionar !se ) e use a seta para cima para obter o comando desejado do histórico. De uma forma ou de outra, eu geralmente recomendo praticar essas coisas imediatamente . Assim, você irá bombear suas habilidades diárias de trabalho no bash e no próprio Vim, como essencialmente você está fazendo a mesma coisa.


No final, todo esse comando pode ser atribuído a uma tecla de atalho ou resumido em uma função e reutilizado em qualquer lugar por um ou dois.


Usando PL de terceiros


Em vez de lançar algo do coreutils, você pode executar o intérprete de algum tipo de linguagem que seja conveniente para você, eu gosto de fazer essas coisas através do Perl6 (recentemente renomeado para Raku ):


 :'<,'>!perl6 -e 'my @x=lines.map(*.subst(/<[,\s]>\s(\w)/,{$0})).sort(*.lc); @x.shift.subst(/\w/,{q/ /~$_}).say; .subst(/\w/,{q/, /~$_}).say for @x' 

Sim, pelo menos no zoskoscript (node.js):


 :'<,'>!node -e 'let fs=require("fs"), x=fs.readFileSync(process.stdin.fd).toString().replace(/\n$/,'').split(/\n/).map(x=>x.replace(/[, ] (\w)/,"$1")).sort((a,b)=>a.toLowerCase().localeCompare(b.toLowerCase())); console.log(x.shift().replace(/(\w)/," $1")); process.stdout.write(x.map(x=>x.replace(/(\w)/,", $1")).join("\n"))' 

Isso também pode ser feito no VimL / Vimscript dentro do próprio Vim, sem chamar comandos externos. Mas este post não é sobre isso.


Naturalmente, como você deve ter adivinhado, você pode salvar seu script facilmente em um arquivo separado ou até compilar seu próprio programa que requer algo para inserir STDIN e gera algo processado no STDOUT e usa-o no Vim simplesmente chamando ( , novamente, pode ser atribuído a uma tecla de atalho):


 :'<,'>!~/my-program-or-script 

Portanto, quando você escreve código no Vim, não apenas o Vim está à sua disposição, mas também todo o seu ambiente de trabalho.


Um dos exemplos mais simples é rejeitar um arquivo JSON:


 :%!jq 

Apenas algumas teclas, por que reinventar o analisador AST e o prettifayer para JSON para qualquer novo editor / IDE / qualquer outra coisa, quando você pode simplesmente executar e executar um arquivo através do jq sem sair do Vim? Não estou falando do fato de que através do jq você pode processar seu arquivo JSON grande sem sair do Vim, encontrar, por exemplo, a chave desejada na árvore, classificar, deixar apenas os dados necessários, etc.

Source: https://habr.com/ru/post/pt483580/


All Articles