Wikia

Vim Tips Wiki

Ipkiss/Restoring part of an original tip

Talk0
1,610pages on
this wiki

< User:Ipkiss

PrincipleEdit

To restore parts of the text from the original tips on vim.org, the idea is the following:

  • make a visual selection of some text (in a wiki tip)
  • transform this text into a clever regular expression matching the same text, but in the same format as it is in the vim.org original tip (this involves escaping some characters, replacing newlines with <br>, etc...)
  • find in the vim.org tip the text matching the clever regexp
  • transform this text back into what the wiki expects
  • replace the visual selection with the transformed text

This is very safe, because the regular expression is extremely precise, we cannot get bad matches (or more precisely, we can, but these matches would then be identical to the good match, modulo some whitespace/end of line).

For more efficiency of the script, I provide a ready-to-use package with all the tips from vim.org, to which I applied some post-processing, detailed at the bottom of this page. In particular I have removed all the embedded \r characters (see Using vim to edit tips to understand why they are problematic).

InstallationEdit

  • Add the following to the Wikipedia.vim ftplugin, or to your .vimrc:
function! GetOriginalIndent()
    let old_reg1 = @w
    let old_reg2 = @/
    let old_hidden = &hidden
    try
        normal gv"wy
        " Get tip number
        let tip_line = search('^|id=\d\+$', "wn")
        if !tip_line
            echoerr "Could not find tip number"
            return
        endif
        let tip_num = substitute(getline(tip_line), '.*=', "", "")
        " Open the tip
        set hidden
        exe "e " . g:vim_tips_dir . "/tip" . tip_num

        " Prepend a newline and escape special regexp characters
        let pattern = escape("\n" . @", '\\/.*$^~[]')
        " Escape html special characters the way they are expected on
        " vim.org tips
        let pattern = substitute(pattern, '&amp;', '\&', "g")
        let pattern = substitute(pattern, '"', '\&quot;', "g")
        " Match vim.org html code
        let pattern = substitute(pattern, " *\n *", '\\s*\\%(<br>\\)*\\%(\&nbsp;\\)*', "g")
        " Search the new pattern in the buffer from vim.org
        let line_num = search(pattern)
        if line_num
            let line = getline(line_num)
            let pos_begin = match(line, pattern)
            let pos_end = matchend(line, pattern, pos_begin)
            let html_text = line[pos_begin : pos_end - 1]
        else
            bd
            " echoerr "Pattern not found in the tip from vim.org: " . pattern
            echoerr "Pattern not found in the tip from vim.org, sorry"
            return
        endif
        " Transform the html back into wiki format
        let final_text = substitute(html_text, "&nbsp;", ' ', "g")
        let final_text = substitute(final_text, "<br>", "\n", "g")
        " No need to escape quotes in the wiki...
        let final_text = substitute(final_text, "&quot;", '"', "g")
        " ... but we do need to restore &amp;
        let final_text = substitute(final_text, '&\(amp;\|gt;\|lt;\|#\d\+;\)\@!', '\&amp;', "g")
        let g:debug = final_text
        " Back to the original buffer
        bd
        " Replace selection with the final text
        let @w = final_text
        normal gv"wpdd'>k
    finally
        " Restore registers
        let @/ = old_reg2
        let @w = old_reg1
        let &hidden = old_hidden
    endtry
endfunction

vmap z <esc>:call GetOriginalIndent()<cr>
  • Define in your .vimrc a variable indicating where you extracted the tips (adapt the path, of course):
let g:vim_tips_dir = "~/vimtips"

UsageEdit

  • Edit a tip with Vim on the wiki
  • Make a visual line selection (using V)
    • Do not use a character-wise or block-wise visual selection if you don't like bad surprises :)
    • Do not span the selection out of the tip itself, or out of one of the comments
    • Do not select the signatures in the comments
  • Hit z
  • Enjoy

If the script didn't manage to find the highlighted text in the original tip, it will output an error message and do nothing. You can of course undo the action of the script using u.


TroubleshootingEdit

  • If you get the message "Could not find tip number", make sure that you have set the g:vim_tips_dir variable properly... and that you are really editing a tip migrated from vim.org!
  • If you get the message "Pattern not found in the tip from vim.org, sorry":
    • Make sure you did the visual selection as described in the Usage section above
    • Try with a smaller selection first (use gv to reselect the previous selection, and o to go from one side of the selection to the other one)
  • If there was no error, but the indentation is still bad, it's probably that the original tip on vim.org had a bad indentation already. Too bad... At least you may have fixed line spacing issues :)
  • You may get an extra empty line before or after the part of the text you restored. I am not sure whether it is a bug in the script or the effect described in :help v_p. I probably won't bother fixing this issue.
  • The script has been well tested, but if you detect a bug notify me and I will try to fix it.


Notes concerning the tips archiveEdit

Here is how the archive has been made:

  • download all the tips using wget
  • (optional) get rid of the empty ones (like this one)
  • open them all in a vim instance, and run:
:sil! bufdo %s/\r//g
:bufdo exe "norm gg0d/code\<cr>5i\<cr>"
:bufdo exe "norm /^<!-- finish off the framework -->$\<cr>dG5o"
:sil! bufdo %s/\(<br>\|&nbsp;\)\@<!\(&nbsp;\)\+/ /g
:sil! wqa

That's all.

Around Wikia's network

Random Wiki