2009-04-01 11 views
12

Sé que puedo usar AWK pero estoy en una caja de Windows. Estoy haciendo una función para otros que pueden no tener AWK. También sé que puedo escribir un programa C, pero me encantaría no tener que crear mantener y compilar algo para una pequeña utilidad de Vim que estoy creando.¿Puedo transportar un archivo en Vim?

El archivo original podría ser

THE DAY WAS LONG 
THE WAY WAS FAST 

y se convertiría

TT 
HH 
EE 

DW 
AA 
YY 

WW 
AA 
SS 

LF 
OA 
NS 
GT 

ACTUALIZACIÓN: las reglas del golf se aplican a la selección de respuesta correcta.

ACTUALIZACIÓN: Los fanáticos de Python deben consultar la respuesta del Sr. Duffy a continuación.

+0

Pardon - "golf"? –

+2

Número más bajo de caracteres ... el puntaje más bajo gana el tipo de cosa. – ojblass

+0

Hubiera sido incluso mejor si la solución transpuso solo el texto seleccionado ...Pero, está bien, la solución actual es lo suficientemente buena para mí. :) –

Respuesta

12

Aquí es un comando en lenguaje Vim. Entonces no tienes que compilar Vim con el soporte de + 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() 

poner esto en el archivo .vim recién creado dentro de vim/dir plugin o poner esto en tu [._] vimrc.
Ejecutar :TransposeBuffer transponer búfer en

+0

Pure vim te da el visto bueno. Muchas gracias! – ojblass

+0

Una solución innecesariamente prolija, en mi opinión. Por cierto, técnicamente hablando su solución no funciona, ya que '1, $" _ d' no hace lo que probablemente quiera hacer. Yo escribiría esa línea como 'sil% d_'. –

+0

@ib por qué lo dice no funciona? Me funciona y elimina todo el archivo en el registro anónimo, ¿no? –

10

Vim soporte para una serie de lenguajes de scripts integrados - vea the Python interface como ejemplo.

Simplemente modifique vim.current.buffer correctamente y está listo.

a ser un poco más específico:

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 - ¡no sabía que vim soportaba más que vimscript! También perl, tcl y ruby ​​- ¡increíble! – guns

+1

Es compatible con esas secuencias de comandos, pero no de forma predeterminada. Debes encenderlos durante la compilación. –

+0

Derecha. Casi todas las distribuciones tienen una versión vim-full o vim-enhanced, y probé lo que publiqué aquí en contra de Windows gvim –

5

Si scripts no lo haga por usted, usted podría registrar las acciones a un registro (se añaden los retornos de carro para facilitar la lectura):

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

Esto le dará usted una macro que podría ejecutar contra el ejemplo anterior, o cualquier cadena de 2 líneas de la misma longitud. Sólo se necesita conocer la longitud de la cuerda para que pueda repetir la operación el número correcto de tiempo

[email protected] 

Una solución bastante básico, pero funciona.

+1

El dominio de entrada podría tener más de dos líneas con la misma longitud. – ojblass

0

Charles Duffy's code podría abreviarse/mejorado usando izip_longest en lugar de 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 siguiente función realiza requiere operaciones de edición para "incorporar" los contenido del búfer en uso.

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 

continuación es su versión de una línea,

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 : ¿No es esta secuencia de comandos la solución más corta de Vim (en un sentido de "golf" que ha declarado como una regla decisiva para seleccionar respuestas) entre las publicadas hasta ahora, ¿verdad? –

0

he desarrollado un plugin vim para hacerlo. Puede encontrarlo here. Ejecute :Transpose para transponer el archivo completo.

Cuestiones relacionadas