Come impostare Vim per lavorare con una frase per riga?


17

Attualmente sto scrivendo un sacco di testo semplice (e LaTeX con una formattazione minima in paragrafi), e sarebbe bello se potessi impostare Vim per mantenere ogni frase (per semplicità, testo terminato da un '.', '!' o "?", ovvero una punteggiatura finale seguita da uno spazio in modo da evitare la rottura dei numeri decimali) sulla propria riga in modo che le differenze VCS siano più utili.

Come minimo, vorrei gqformattare il testo da:

He lay flat on the brown, pine-needled floor of the forest, his chin on his
folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he
could see the dark of the oiled road winding through the pass. There was a
stream alongside the road and far down the pass he saw a mill beside the
stream and the falling water of the dam, white in the summer sunlight. 

Per:

He lay flat on the brown, pine-needled floor of the forest, his chin on his folded arms, and high overhead the wind blew in the tops of the pine trees.
The mountainside sloped gently where he lay; but below it was steep and he could see the dark of the oiled road winding through the pass.
There was a stream alongside the road and far down the pass he saw a mill beside the stream and the falling water of the dam, white in the summer sunlight.

Ma sarebbe bello se Vim eseguisse anche questa formattazione mentre scrivo (come fa con il reflow della larghezza del testo). È possibile?

La mia attuale soluzione è quella di unire un paragrafo J, quindi eseguire :'<,'>s/\. /.\r/gche è abbastanza buono in quanto vi sono pochi punti esclamativi e punti interrogativi, ma sarebbe molto meglio se potessi rendere gq leggermente più intelligente.

Risposte:


23

L' 'formatexpr'opzione

Puoi farlo usando l' 'formatexpr'opzione. Dall'aiuto:

Espressione che viene valutata per formattare un intervallo di righe per l'operatore gq o la formattazione automatica (vedere "formatoptions"). Quando questa opzione è vuota, viene utilizzato 'formatprg'.

L'impostazione 'formatexpr'corretta funzionerà sia durante l'utilizzo gqche durante l'inserimento del testo.

Un semplice esempio

Ecco una semplice funzione VimScript e il 'formatexpr'valore corrispondente che dovrebbe fare il lavoro. Non l'ho provato su tutti i casi limite, ma ha funzionato bene per i miei semplici test.

function! MyFormatExpr(start, end)
    silent execute a:start.','.a:end.'s/[.!?]\zs /\r/g'
endfunction

set formatexpr=MyFormatExpr(v:lnum,v:lnum+v:count-1)

Spiegazione

L'espressione è una chiamata alla funzione MyFormatExpr(), che passa nelle righe iniziale e finale su cui verrà applicata la formattazione. Queste righe vengono calcolate utilizzando le variabili popolate automaticamente v:lnum(la prima riga da formattare) e v:count(il numero di righe da formattare).

La MyFormatExpr()funzione crea un :substitutecomando con il passato nella gamma, e sostituisce uno spazio bianco a seguito di un segno di punteggiatura end-of-sentence ( ., !, o ?), con un ritorno a capo ( \r).

Avvertenze

  • La MyFormatExpr()funzione non preserva il rientro iniziale. Qualche logica più sofisticata sarebbe necessaria per risolvere questo problema.
  • Potrebbero esserci altri casi limite in cui ciò cade a pezzi. Fai un test drive e modifica se necessario!

Oh, sì, questa è la strada da percorrere, ignora la mia risposta.
Sukima,

Questo e spettacolare! Quello che vorrei poter fare è far eseguire una funzione alla macro, come "vai avanti alla frase successiva )e inserisci una nuova riga; ripeti fino ad arrivare alla fine dell'intervallo". Quindi presumibilmente applicherebbe eventuali regole di rientro. Ma il mio Vim-fu è troppo debole per quello. :)
Nathan Long,

Questo si divide ad esempio e.g. blah, e Blah et al. 2018che è un po 'fastidioso. È possibile annullare la corrispondenza di modelli come quello con qualcosa del genere 's/\(e\.g\|\<al\)\@<![.!?]\zs /\r/g'. Aggiungi solo altri schemi al primo gruppo per evitare altre cose su cui non vuoi dividere. Altrimenti, questo è super utile, grazie. Non mi ero mai imbattuto in gqprecedenza, ed gqipè super utile per la formattazione del testo che gli editor di testo del coautore hanno rovinato.
naught101

C'è un modo per aggiungere questo comportamento al comportamento predefinito? Vorrei essere in grado di racchiudere una data larghezza del testo, oltre a suddividere alla fine delle frasi ..
niente101

1

Bene, puoi configurare alcune mappe e i comandi automatici:

function! AddSentenceMaps()
  imap .<Space> .<CR>
  imap !<Space> !<CR>
  imap ?<Space> ?<CR>
  exec "nmap gq vipJ:s/\\([.!?]\\)\\s\\+/\\1\\r/g<CR>"
endfunction

autocmd Filetype customtxt call AddSentenceMaps()

Quindi imposta il tipo di file su customtxt o chiama la AddSentenceMapsfunzione manualmente.


0

Voglio aggiungere i miei pensieri su questo problema. Di solito le persone vogliono questo tipo di funzionalità a causa di saltare le linee tratteggiate quando navigano nel codice con je kcomandi che è il comportamento predefinito di Vim. Per la navigazione attraverso le linee tratteggiate uso gj- sposta in basso e gk- sposta in alto. Inoltre c'è la possibilità di rimappare lo standard je il kcomando sulle controparti con prefisso g, ma IMHO sarebbe eccessivo.


o di avere una chiave per farlo remaping di je kper gje gkquando vuoi ;-)
anthony

0

Non risponde alla tua domanda specifica sulla riformattazione, ma 'set wrap' insieme a 'set linebreak' può rendere molto più piacevole la modifica di linee lunghe. Combina questo con gj e gk per navigare all'interno delle linee avvolte. Mappare le frecce su e giù rispettivamente su gj e gk in modo da scegliere tra spostarsi su e giù su linee reali o linee visive. Come saggio per Home / Fine a g0 / g $.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.