2009-04-01 19 views
12

So che posso usare AWK ma sono su una casella di Windows. Sto facendo una funzione per gli altri che potrebbero non avere AWK. So anche che posso scrivere un programma in C, ma mi piacerebbe non dover creare e compilare qualcosa per una piccola utility Vim che sto realizzando.Posso trasporre un file in Vim?

Il file originale potrebbe essere

THE DAY WAS LONG 
THE WAY WAS FAST 

e sarebbe diventato

TT 
HH 
EE 

DW 
AA 
YY 

WW 
AA 
SS 

LF 
OA 
NS 
GT 

UPDATE: regole di golf si applicano alla selezione risposta corretta.

AGGIORNAMENTO: I fan di Python dovrebbero controllare la risposta di Mr. Duffy sotto.

+0

Pardon - "golf"? –

+2

Il minor numero di caratteri ... il punteggio più basso vince il genere di cose. – ojblass

+0

Sarebbe stato ancora meglio se la soluzione trasposto solo il testo selezionato ...Ma, okay, la soluzione corrente è abbastanza buona per me. :) –

risposta

12

Ecco un comando in lingua Vim. Quindi non devi compilare Vim con il supporto + python.

function! s:transpose() 
    let maxcol = 0 
    let lines = getline(1, line('$')) 

    for line in lines 
     let len = len(line) 
     if len > maxcol 
      let maxcol = len 
     endif 
    endfor 

    let newlines = [] 
    for col in range(0, maxcol - 1) 
     let newline = '' 
     for line in lines 
      let line_with_extra_spaces = printf('%-'.maxcol.'s', line) 
      let newline .= line_with_extra_spaces[col] 
     endfor 
     call add(newlines, newline) 
    endfor 

    1,$"_d 
    call setline(1, newlines) 
endfunction 

command! TransposeBuffer call s:transpose() 

mettere questo nel file di .vim appena creato all'interno vim/plugin dir o mettere questo al tuo [._] vimrc.
Esegui :TransposeBuffer trasporre buffer corrente

+0

Pure vim ti fa il cenno del capo. Grazie mille! – ojblass

+0

Una soluzione inutilmente prolissa, secondo me. A proposito, tecnicamente parlando la tua soluzione non funziona, dal momento che '1, $" _ d' non fa quello che probabilmente vuoi che faccia: scriverò quella riga come 'sil% d_'. –

+0

@ib perché lo dici no? Funziona per me ed elimina l'intero file nel registro anonimo, non è vero? –

10

Supporto Vim per un certo numero di linguaggi di scripting integrati - vedere the Python interface come esempio.

Basta modificare vim.current.buffer in modo appropriato e sei pronto.

Per essere un po 'più specifico:

function! Rotate() 
python <<EOF 
import vim, itertools 
max_len = max((len(n) for n in vim.current.buffer)) 

vim.current.buffer[:] = [ 
    ''.join(n) for n in itertools.izip(
     *(n + ' ' * (max_len - len(n)) 
      for n in vim.current.buffer))] 
EOF 
endfunction 
+1

++ oooh - non era a conoscenza del fatto che vim supportasse più di vimScript! Anche perl, tcl e ruby ​​- fantastico! – guns

+1

Supporta quegli script ma non per impostazione predefinita. Devi accenderli durante la compilazione. –

+0

Giusto. Quasi tutte le distribuzioni hanno una versione vim-full o vim-enhanced, e ho provato quello che ho postato qui contro il gvim di Windows –

5

Se gli script non lo fanno per te, è possibile registrare le azioni a un registro (i ritorni a capo vengono aggiunti per migliorare la leggibilità):

qa 
1G0 
xGo<Esc>p 
1G0j 
xGp 
q 

Questo darà una macro che potresti eseguire nell'esempio precedente o qualsiasi stringa a 2 righe della stessa lunghezza. Hai solo bisogno di conoscere la lunghezza della stringa in modo da poter scorrere l'operazione il numero corretto di tempo

[email protected] 

Una soluzione abbastanza semplice, ma funziona.

+1

Il dominio di input potrebbe essere più di due righe con la stessa lunghezza – ojblass

0

Charles Duffy's code potrebbe essere abbreviata/migliorata utilizzando izip_longest anziché izip:

function! Rotate() 
    :py import vim, itertools 
    :py vim.current.buffer[:] = [''.join(c) for c in itertools.izip_longest(*vim.current.buffer, fillvalue=" ")] 
endfunction 
1

La seguente funzione esegue operazioni di modifica tenuti a "recepire" i contenuto del buffer corrente.

fu!T() 
let[m,n,@s]=[0,line('$'),"lDG:pu\r``[email protected]"] 
g/^/let m=max([m,col('$')]) 
exe'%norm!'.m."A \e".m.'|D' 
[email protected] 
exe'%norm!'.n.'gJ' 
endf 

Qui di seguito è la sua versione di una riga,

let[m,n,@s]=[0,line('$'),"lDG:pu\r``[email protected]"]|exe'g/^/let m=max([m,col("$")])'|exe'%norm!'.m."A \e".m.'|D'|exe'[email protected]'|exe'%norm!'.n.'gJ' 
+0

@ojblass : Non è questo script la soluzione Vim-only più corta (in un senso "golf" che hai dichiarato come regola decisiva per la selezione delle risposte) tra quelle pubblicate finora, vero? –

0

ho sviluppato un plugin vim per farlo. Lo puoi trovare here. Eseguire :Transpose per trasporre l'intero file.

Problemi correlati