tutorial pegar linea insertar inicio español copiar busquedas buscar vim

pegar - Función de conteo rápido de palabras en Vim



vim linux (13)

Aquí hay un refinamiento de la respuesta de Abslom Daak que también funciona en modo visual.

function! WordCount() let s:old_status = v:statusmsg let position = getpos(".") exe ":silent normal g/<c-g>" let stat = v:statusmsg let s:word_count = 0 if stat != ''--No lines in buffer--'' if stat =~ "^Selected" let s:word_count = str2nr(split(v:statusmsg)[5]) else let s:word_count = str2nr(split(v:statusmsg)[11]) end let v:statusmsg = s:old_status end call setpos(''.'', position) return s:word_count endfunction

Incluido en la línea de estado como antes. Aquí hay una línea de estado alineada a la derecha:

set statusline=%=%{WordCount()}/ words/

Estoy tratando de mostrar un recuento de palabras en vivo en la línea de estado de vim. Lo hago estableciendo mi línea de estado en mi .vimrc e insertando una función en ella. La idea de esta función es devolver el número de palabras en el búfer actual. Este número se muestra en la línea de estado. Esto debería funcionar bien ya que la línea de estado se actualiza en casi todas las oportunidades posibles, por lo que el recuento siempre permanecerá "en vivo".

El problema es que la función que tengo definida actualmente es lenta y, por tanto, vim es obviamente lenta cuando se usa para todos los archivos, excepto para los más pequeños; debido a que esta función se ejecuta con tanta frecuencia.

En resumen, ¿alguien tiene un truco ingenioso para producir una función que es tremendamente rápida al calcular el número de palabras en el búfer actual y devolver el resultado?


Aquí hay una versión utilizable de la idea de Rodrigo Queiro. No cambia la barra de estado, y restaura la variable statusmsg.

function WordCount() let s:old_status = v:statusmsg exe "silent normal g/<c-g>" let s:word_count = str2nr(split(v:statusmsg)[11]) let v:statusmsg = s:old_status return s:word_count endfunction

Esto parece ser lo suficientemente rápido como para incluirlo directamente en la línea de estado, por ejemplo:

:set statusline=wc:%{WordCount()}


Así que he escrito:

func CountWords() exe "normal g/" let words = substitute(v:statusmsg, "^.*Word [^ ]* of ", "", "") let words = substitute(words, ";.*", "", "") return words endfunc

Pero imprime información en la barra de estado, por lo que no creo que sea adecuada para su caso de uso. ¡Es muy rápido, sin embargo!


En caso de que alguien más venga desde Google, modifiqué la respuesta de Abslom Daak para trabajar con Airline . Guardé lo siguiente como

~/.vim/bundle/vim-airline/autoload/airline/extensions/pandoc.vim

y agregado

call airline#extensions#pandoc#init(s:ext)

a extensions.vim

let s:spc = g:airline_symbols.space function! airline#extensions#pandoc#word_count() if mode() == "s" return 0 else let s:old_status = v:statusmsg let position = getpos(".") let s:word_count = 0 exe ":silent normal g/<c-g>" let stat = v:statusmsg let s:word_count = 0 if stat != ''--No lines in buffer--'' let s:word_count = str2nr(split(v:statusmsg)[11]) let v:statusmsg = s:old_status end call setpos(''.'', position) return s:word_count end endfunction function! airline#extensions#pandoc#apply(...) if &ft == "pandoc" let w:airline_section_x = "%{airline#extensions#pandoc#word_count()} Words" endif endfunction function! airline#extensions#pandoc#init(ext) call a:ext.add_statusline_func(''airline#extensions#pandoc#apply'') endfunction


Esta es una mejora en la versión de Michael Dunn , almacenando en caché el conteo de palabras, por lo que aún se necesita menos procesamiento.

function! WC() if &modified || !exists("b:wordcount") let l:old_status = v:statusmsg execute "silent normal g/<c-g>" let b:wordcount = str2nr(split(v:statusmsg)[11]) let v:statusmsg = l:old_status return b:wordcount else return b:wordcount endif endfunction


Esto recalculará el número de palabras cada vez que deje de escribir durante un tiempo (específicamente, updatetime ms).

let g:word_count="<unknown>" fun! WordCount() return g:word_count endfun fun! UpdateWordCount() let s = system("wc -w ".expand("%p")) let parts = split(s, '' '') if len(parts) > 1 let g:word_count = parts[0] endif endfun augroup WordCounter au! CursorHold * call UpdateWordCount() au! CursorHoldI * call UpdateWordCount() augroup END " how eager are you? (default is 4000 ms) set updatetime=500 " modify as you please... set statusline=%{WordCount()}/ words

¡Disfrutar!


Mantenga un conteo para la línea actual y un conteo separado para el resto del buffer. A medida que escribe (o elimina) palabras en la línea actual, actualice solo ese conteo, pero muestre la suma del conteo de línea actual y el resto del recuento de memoria intermedia.

Cuando cambie líneas, agregue el recuento de línea actual al recuento de memoria intermedia, cuente las palabras en la línea actual y a) establezca el recuento de línea actual y b) reste de la cuenta de memoria intermedia.

También sería aconsejable volver a contar el búfer de forma periódica (tenga en cuenta que no tiene que contar todo el búfer de una vez, ya que sabe dónde se está produciendo la edición).


Me gustó mucho la respuesta de Michael Dunn, pero descubrí que cuando editaba no podía acceder a la última columna. Así que tengo un cambio menor para la función:

function! WordCount() let s:old_status = v:statusmsg let position = getpos(".") exe ":silent normal g/<c-g>" let stat = v:statusmsg let s:word_count = 0 if stat != ''--No lines in buffer--'' let s:word_count = str2nr(split(v:statusmsg)[11]) let v:statusmsg = s:old_status end call setpos(''.'', position) return s:word_count endfunction

Lo he incluido en mi línea de estado sin ningún problema:

:set statusline=wc:%{WordCount()}


Mi sugerencia:

function! UpdateWordCount() let b:word_count = eval(join(map(getline("1", "$"), "len(split(v:val, ''//s//+''))"), "+")) endfunction augroup UpdateWordCount au! autocmd BufRead,BufNewFile,BufEnter,CursorHold,CursorHoldI,InsertEnter,InsertLeave * call UpdateWordCount() augroup END let &statusline=''wc:%{get(b:, "word_count", 0)}''

No estoy seguro de cómo se compara en velocidad con algunas de las otras soluciones, pero ciertamente es mucho más simple que la mayoría.


Soy nuevo en el scripting de Vim, pero podría sugerir

function WordCount() redir => l:status exe "silent normal g/<c-g>" redir END return str2nr(split(l:status)[11]) endfunction

como un poco más limpio ya que no sobrescribe la línea de estado existente.

Mi razón para publicar es señalar que esta función tiene un error desconcertante: es decir, rompe el comando de agregar. Al presionar A debe colocarse en el modo de inserción con el cursor colocado a la derecha del carácter final en la línea. Sin embargo, con esta barra de estado personalizada habilitada, te pondrá a la izquierda del personaje final.

Alguien tiene alguna idea de lo que hace esto?


Tomé la mayor parte de esto de las páginas de ayuda de vim sobre las funciones de escritura.

function! WordCount() let lnum = 1 let n = 0 while lnum <= line(''$'') let n = n + len(split(getline(lnum))) let lnum = lnum + 1 endwhile return n endfunction

Por supuesto, como los demás, necesitarás:

:set statusline=wc:%{WordCount()}

Estoy seguro de que esto puede ser limpiado por alguien para que sea más vimmy (s: n en lugar de simplemente n?), Pero creo que la funcionalidad básica está ahí.

Editar:

Al ver esto de nuevo, realmente me gusta la solución de Mikael Jansson. No me gusta bombardear a wc (no portátil y quizás lento). Si reemplazamos su función UpdateWordCount con el código que tengo arriba (renombrando mi función a UpdateWordCount ), entonces creo que tenemos una mejor solución.


Usé un enfoque ligeramente diferente para esto. En lugar de asegurarme de que la función de conteo de palabras sea especialmente rápida, solo la invoco cuando el cursor deja de moverse. Estos comandos lo harán:

:au CursorHold * exe "normal g/<c-g>" :au CursorHoldI * exe "normal g/<c-g>"

Tal vez no exactamente lo que quería el interrogador, pero es mucho más simple que algunas de las respuestas aquí, y lo suficientemente bueno para mi caso de uso (mire hacia abajo para ver el recuento de palabras después de escribir una o dos oraciones).

Establecer el tiempo de updatetime a un valor más pequeño también ayuda aquí:

set updatetime=300

No hay un gran CursorHold aéreo para el recuento de palabras porque CursorHold y CursorHoldI solo disparan una vez cuando el cursor deja de moverse, no cada updatetime ms.


Usando el método en la respuesta proporcionada por Steve Moyer, pude producir la siguiente solución. Es un truco bastante poco elegante, me temo, y creo que debe haber una solución más ordenada, pero funciona, y es mucho más rápido que simplemente contar todas las palabras en un buffer cada vez que se actualiza la línea de estado. También debo señalar que esta solución es independiente de la plataforma y no supone que un sistema tenga ''wc'' o algo similar.

Mi solución no actualiza periódicamente el búfer, pero la respuesta proporcionada por Mikael Jansson podría proporcionar esta funcionalidad. Hasta el momento, no he encontrado una instancia en la que mi solución no esté sincronizada. Sin embargo, solo he probado esto brevemente, ya que un conteo exacto de palabras en vivo no es esencial para mis necesidades. El patrón que uso para emparejar palabras también es simple y está destinado a documentos de texto simples. Si alguien tiene una mejor idea para un patrón o cualquier otra sugerencia, no dude en publicar una respuesta o editar esta publicación.

Mi solución:

"returns the count of how many words are in the entire file excluding the current line "updates the buffer variable Global_Word_Count to reflect this fu! OtherLineWordCount() let data = [] "get lines above and below current line unless current line is first or last if line(".") > 1 let data = getline(1, line(".")-1) endif if line(".") < line("$") let data = data + getline(line(".")+1, "$") endif let count_words = 0 let pattern = "//<//(//w//|-//|''//)//+//>" for str in data let count_words = count_words + NumPatternsInString(str, pattern) endfor let b:Global_Word_Count = count_words return count_words endf "returns the word count for the current line "updates the buffer variable Current_Line_Number "updates the buffer variable Current_Line_Word_Count fu! CurrentLineWordCount() if b:Current_Line_Number != line(".") "if the line number has changed then add old count let b:Global_Word_Count = b:Global_Word_Count + b:Current_Line_Word_Count endif "calculate number of words on current line let line = getline(".") let pattern = "//<//(//w//|-//|''//)//+//>" let count_words = NumPatternsInString(line, pattern) let b:Current_Line_Word_Count = count_words "update buffer variable with current line count if b:Current_Line_Number != line(".") "if the line number has changed then subtract current line count let b:Global_Word_Count = b:Global_Word_Count - b:Current_Line_Word_Count endif let b:Current_Line_Number = line(".") "update buffer variable with current line number return count_words endf "returns the word count for the entire file using variables defined in other procedures "this is the function that is called repeatedly and controls the other word "count functions. fu! WordCount() if exists("b:Global_Word_Count") == 0 let b:Global_Word_Count = 0 let b:Current_Line_Word_Count = 0 let b:Current_Line_Number = line(".") call OtherLineWordCount() endif call CurrentLineWordCount() return b:Global_Word_Count + b:Current_Line_Word_Count endf "returns the number of patterns found in a string fu! NumPatternsInString(str, pat) let i = 0 let num = -1 while i != -1 let num = num + 1 let i = matchend(a:str, a:pat, i) endwhile return num endf

Esto luego se agrega a la línea de estado al:

:set statusline=wc:%{WordCount()}

Espero que esto ayude a cualquiera que esté buscando un recuento de palabras en vivo en Vim. Aunque uno que no siempre es exacto. ¡Alternativamente, por supuesto, g ctrl-g le proporcionará el recuento de palabras de Vim!