¿Puedo ver los cambios antes de guardar mi archivo en Vim?

135

Yo uso Vim Abro un archivo. Lo edito y quiero ver lo que he editado antes de guardarlo.

¿Cómo puedo hacer esto en Vim?

teerapap
fuente

Respuestas:

57

http://vim.wikia.com/wiki/Diff_current_buffer_and_the_original_file

Aquí hay una función y un comando para ver una diferencia entre el archivo editado actualmente y su versión no modificada en el sistema de archivos. Simplemente colóquelo en su vimrc o en el directorio de complementos, abra un archivo, realice algunas modificaciones sin guardarlas y hágalo :DiffSaved.

function! s:DiffWithSaved()
  let filetype=&ft
  diffthis
  vnew | r # | normal! 1Gdd
  diffthis
  exe "setlocal bt=nofile bh=wipe nobl noswf ro ft=" . filetype
endfunction
com! DiffSaved call s:DiffWithSaved()

Para salir de la vista de diferencias, puede usar el :diffoffcomando.

A continuación se muestra una función similar, adaptada para imitar el 'cvs diff'comando ...

Bill Lynch
fuente
77
@ luc-hermitte ¿No es la alternativa :w !diff % -superior cuando usas vim en una gran cantidad de cajas en constante cambio por las que no puedes cambiar fácilmente el .vimrc? (Siempre que tengan instalado diff.)
thomanski
1
Vim no es la herramienta de la última esperanza. El que funcionará cuando no haya nada más disponible. Es mi principal herramienta de trabajo.
Luc Hermitte
12
Solo proporcionar un enlace no es realmente una respuesta
Skurpi
3
La respuesta del Caos es superior y en la respuesta de Tobias, la explicación está completa.
Avi Cohen
1
¿Puedes agregar algún contenido en lugar de solo un enlace? Directrices SO ...
Błażej Michalik
160
:w !diff % -
caos
fuente
44
¿Hay alguna manera de hacer esto con vimdiff? Intenté: w! Vimdiff%, pero sin éxito.
Joe J
14
¿Alguien puede explicar eso? No entiendo lo que está pasando. Entiendo que estás bombardeando diff. %se refiere a la ruta de archivo abierta actualmente. ¿Por qué todo esto es un argumento para el :wcomando? Además, ¿cómo -se asigna al contenido del búfer de trabajo? ¿Es eso automático en vim, que el contenido del búfer (o tal vez un rango específico en el búfer) se asigne a stdin para los comandos de shell?
Nathan Wallace
9
@NathanWallace: Es un argumento :wporque estamos escribiendo el archivo en el comando ( activado stdin). En el comando, -le dice que lea stdin.
caos
14
¡O :w !git diff % -úselo para una versión coloreada, si tiene instalado git!
Dergachev
55
@ Dergachev Me sale el error fatal: bad flag '-' used after filenamecuando ejecuto :w !git diff % -.
Escala de grises
100

Porque algunas personas preguntaron acerca de una explicación para el comando

:w !diff % -

Aquí está mi intento de escribir una respuesta más detallada:

Supongo que está trabajando en un sistema cate echoinstalado (por ejemplo, casi cualquier GNU / Linux, Mac OS, BSD y otros sistemas similares a UNIX).

El comando anterior funciona de la siguiente manera:

  1. La sintaxis para guardar un archivo en vim es:

    :w <filename>
    
  2. La sintaxis para ejecutar un comando de shell en vim es:

    :!<command>
    
  3. Dentro del entorno de shell emitido por vim %sucede que apunta al nombre de archivo actual. Puede verificar esto ejecutando lo siguiente:

    :!echo %
    

    Esto debería generar el nombre de archivo (o un error, si vim se ejecutó sin un nombre de archivo).

    Usando cat también podemos generar el contenido del archivo:

    :!cat %
    

    Esto debería devolver el contenido de los archivos en su último estado guardado o un error si nunca se ha guardado.

  4. El programa diff puede leer desde la entrada estándar (stdin). Su página de manual dice lo siguiente:

    [...] Si un ARCHIVO es '-', lea la entrada estándar. [...]

  5. La ejecución del comando guardar sin un nombre de archivo, sino más bien un comando de shell detrás de él, hace que vim escriba el contenido de los archivos en stdin del shell en lugar de guardarlo en un archivo físico. Puede verificar esto ejecutando

    :w !cat
    

    Esto siempre debe imprimir el contenido actual de los archivos (que en su lugar se habría escrito en un archivo).

Poniéndolo junto (o tl; dr): el archivo se "guarda" en stdin, diff se ejecuta con el nombre de archivo y stdin como entrada.

Saber esto también podría comparar archivos con vimdiff haciendo algo como esto: esta es solo una idea que no desea hacer esto:

:w !cat > /tmp/tempFile && vimdiff /tmp/tempFile % && rm /tmp/tempFile

(Luego abra readonly y cierre vimdiff usando :qall)

Tobias Heinicke
fuente
Un enfoque más sensato para usar vimdiff sería crear un script de shell que contenga lo siguiente vim - -c ":vnew $1 |windo diffthis", hacerlo ejecutable, guardarlo en la RUTA como, por ejemplo, vimdiffWithStdiny luego compararlo con el siguiente comando en vim::w !vimdiffWithStdin %
Tobias Heinicke
Aún más simple: :w !vimdiff % /dev/stdin. No sé si existe un truco similar para Windows.
deft_code
12

Siempre me han gustado los cambios : agradable, simple, funciona.

Torre
fuente
Esto funciona MUCHO mejor que las opciones más altamente votadas. Esto le da la capacidad de alternarlo.
Steven Lu
1
@StevenLu - Meh ... ¿qué puedes hacer? En cualquier caso, me alegro de que te guste. Lo encuentro más práctico que el otro enfoque.
Torre de
Yo, segundo @Steven, tus cambios sugeridos son excelentes. ¡Gracias!
AS
Esto también se puede instalar como un complemento del mismo desarrollador: github.com/jmcantrell/vim-diffchanges
Sumanth Lingappa
buen complemento, pero no elimina el parche que crea después? Editar: Mi mal! Lo hace. Lo estaba usando de manera incorrecta. Tuve que usar :DiffChangesDiffToggle.
aderchox hace
10

de vimrc_example.vim:

" Convenient command to see the difference between the current buffer and the
" file it was loaded from, thus the changes you made.
if !exists(":DiffOrig")
  command DiffOrig vert new | set bt=nofile | r # | 0d_ | diffthis
          \ | wincmd p | diffthis
endif
0x89
fuente
... como se documenta en vimdoc.sourceforge.net/htmldoc/diff.html#:DiffOrig . La ventaja de este sobre w !diff % -es que funciona las fuentes más remotas también (por ejemplo: vim sftp://example.com/foo.txt)
Lekensteyn
1
Me gusta más porque vemos la diferencia dentro del búfer vim en lugar de en un terminal
Niko Bellic
¿Cómo vuelves a la normalidad una vez que hayas terminado de examinar las diferencias?
Niko Bellic
¡Puede deshacerse de la cláusula if sustituyendo command por command! (ver: h E174)
elegible el
@NikoBellic Primero cierre la ventana "antigua" (marcada como memoria intermedia de memoria virtual) con ': q'. Puede cambiar entre ventanas tocando ctrl-W dos veces mientras está en modo normal. Luego puede desactivar diff escribiendo: diffoff
brunch875
2

Obtenga lo siguiente y use: comando DIFF

function! s:diff()
    let tmpa = tempname()
    let tmpb = tempname()
    earlier 100h
    exec 'w '.tmpa
    later 100h
    exec 'w '.tmpb
    update
    exec 'tabnew '.tmpa
    diffthis
    vert split
    exec 'edit '.tmpb
    diffthis
endfunction
command! -nargs=0 DIFF call <SID>diff()
Mykola Golubyev
fuente
2

No es exactamente lo que estás buscando, pero SCMDiff.vim es realmente genial. Una pulsación de tecla, y resalta su archivo actual con la revisión de la cabeza en un repositorio de control de fuente. Está destinado a funcionar con muchos SCMS. Lo uso con fuerza.

prestomation
fuente
2

Hay un complemento, basado en diferentes respuestas aquí: https://github.com/gangleri/vim-diffsaved

Proporciona el :w !diff % -método y el más complicado diffthis.

Aparte de eso, unotree permite esto también, pero también mucho más (difiere entre diferentes puntos de control de deshacer). Similar a Gundo .

azulado
fuente
1

Puedo recomendar el complemento histwin .

Si bien no difiere de la versión guardada actual del archivo (como las otras respuestas), puede modificar los cambios desde que comenzó a editar e incluso reproducir los cambios en orden. La diferencia se muestra si ahorra de forma intermedia.

Además, muestra una lista de todas las ramas del historial de deshacer y le permite cambiar o diferenciar entre ellas.

PD: Si bien el complemento no rastrea automáticamente los momentos en el historial de edición desde cada cambio de archivo, puede "etiquetar" explícitamente el momento en que guarda el archivo para que luego pueda verlo, si así lo desea. Tal vez esto podría ser automatizado?

catchmeifyoutry
fuente
1

Si desea usar vim para comparar, como en vimdiff, puede hacer algo como esto:

Edite su .vimrc y agregue:

nmap <F8> :w !vim -M -R - -c ":vnew % \| windo diffthis"<CR><CR>

A partir de ahí, verá sus cambios y puede salir de la vista de diferencias usando qallcomo en vimdiff presionando F8 en modo comando. Reemplace F8 con cualquier tecla que desee.

Editar: Se agregó -M para no permitir ninguna modificación, ya que no se guarda.

Tobias Heinicke
fuente
Este comando comienza a funcionar para mí, me muestra la diferencia de lado a lado. Sin embargo, tan pronto como intento editar algo, la ventana de vim se vuelve loca. Empiezo a escribir y aparece un mensaje bash detrás de las palabras en vim a cada lado de la pantalla. Por lo tanto, parece mostrar la diferencia, pero luego vim se bloquea. Además, me sale este error Vim: Error reading input, exiting...alguna idea de lo que está mal aquí?
Trevor
@Trevor: solo podía adivinar cuáles son los problemas. De hecho, no es seguro realizar modificaciones mientras diferencie de esta manera. Por lo tanto, he agregado el parámetro "-M" para no permitirlo por completo. Lo siento.
Tobias Heinicke
1

git admite el siguiente comando

:w !git diff --no-index -- % -

asignarlo a un comando agregando lo siguiente a su ~ / .vimrc

command GitDiff execute "w !git diff --no-index -- % -"

Ahora ejecutar se :GitDiffconvierte en un pequeño comando útil para mostrar rápidamente la diferencia antes de cada guardado.

Universo cíclico
fuente
0

Puede hacer que vim cree una última copia de seguridad y una copia de seguridad original con:

:set backup
:set patchmode=.orig 

A partir de entonces, puede abrirlos en una división:

:vsp %:p~ or :vsp %:.orig

Y a partir de ahí hacer:

:vimdiff in each buffer

Si no tiene restos, pero quiere vimdiff, también puede hacer lo siguiente:

ggVGy    # copy the whole buffer
:vnew    # open a split
CTRL-W w # switch to it
shift-P  # paste at start

y luego hacer: diffthis en cada división

chipfall
fuente
0

Los cambios que acaba de editar [ tampón ], es decir, aquellos que difieren de la última versión guardada (en el trabajo dir ectory), éstos pueden diferir con la última versión de índice ( Git ). Mapeé ambos:

" Find diff inbetween currrent buffer and ... A{last index version} vs B{last saved version in working directory}
"  - A{last index version}: the file as you last commited it
    " git diff to vimdiff against the index version of the file:
    nnoremap <leader>gd <Esc>:Gvdiff<CR><Esc>:echo "currentBuffer vs lastIndexVersion (last commited)"<CR>
"  - B{last saved version in working directory}: the file you last :w,
"   not neccesary commited it (not commited for sure if it is in NO git project)
    " https://vim.fandom.com/wiki/Diff_current_buffer_and_the_original_file
    nnoremap <leader>gd2 <Esc>:DiffSaved<CR><Esc>:echo "currentBuffer vs lastSaved (not neccesary equal to last commited)"<CR>
    function! s:DiffWithSaved()
        let filetype=&ft
        diffthis
        vnew | r # | normal! 1Gdd
        diffthis
        exe "setlocal bt=nofile bh=wipe nobl noswf ro ft=" . filetype
    endfunction
    com! DiffSaved call s:DiffWithSaved()

Ejemplo de vimdiff vs Gdiff.

  • vimdiff: : vimdiff
  • Gdiff: al Gdiff confirmar los cambios, solo ve Gdiff, lo que podría o podría tener los mismos cambios que vimdiff: confirmando cambios, solo ve Gdiff, lo que podría o NO tener los mismos cambios que vimdiff

Además, para facilitar el vimdiffarchivo de homónimo en otra ruta:

    " vimdiff homonym file 
   nnoremap <leader>dh  <Esc>:vsplit %:p:h/../__/%:t <bar> :windo diffthis<Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left><Left>
        "E.g."$ vim /path01/proj02_pg064/processorder.php
        ":vsplit %:p:h/../proj01_pg05/%:t | :windo diffthis
Xopi García
fuente
1
Uno podría simplemente hacer 1 mapa que se ejecute: a Gdiffsi es posible y de lo contrario (por ejemplo, no es un proyecto Git) y luego realizar a :vimdiff. Con try-catch-endtry. Pero de esta manera :DiffWithSaveden un proyecto Git se carece.
Xopi García
-2

Siga lo anterior sugiere que uso git diff que me gusta mucho:

:w !git diff  % -
Alex
fuente