Skip to content

Instantly share code, notes, and snippets.

@philpennock
Last active March 14, 2018 04:51
Show Gist options
  • Select an option

  • Save philpennock/5ae18a3c753d78cc40c8 to your computer and use it in GitHub Desktop.

Select an option

Save philpennock/5ae18a3c753d78cc40c8 to your computer and use it in GitHub Desktop.
vimscript for a :Div command, taking a range
if has("eval")
" Insert a divider
" Start and end are line numbers.
" Sep is ordinarily the string of characters which make up the divider, but
" if the first and third characters (not bytes) are period, then the second
" character is a single-character line prefix and the third character
" onwards is the divider.
function! s:pdp_div(start, end, sep, ...) range
let l:label = a:0 >= 1 ? join(a:000, ' ') : 'cut here'
if strwidth(a:sep) >= 4 && a:sep[0] == '.' && strcharpart(a:sep, 2, 1) == '.'
let l:prefix = strcharpart(a:sep, 1, 1)
let l:divider_seq = strcharpart(a:sep, 3)
else
let l:divider_seq = a:sep
let l:prefix = ''
endif
let l:width = (&tw != 0) ? &tw : 72
let l:first = (a:start == a:end) ? a:start : a:start - 1
let l:center = '8< ' . l:label . ' >8'
let l:divreq = (l:width - strwidth(l:center) - strwidth(l:prefix)) / strwidth(l:divider_seq)
if l:divreq <= 0
let l:line = l:center
else
let l:pre = l:divreq / 2
let l:post = l:divreq - l:pre
let l:line = l:prefix . repeat(l:divider_seq, l:pre) . l:center . repeat(l:divider_seq, l:post)
endif
if a:start != a:end
call append(a:end, l:line)
endif
call append(l:first, l:line)
call cursor(a:end+2, 0)
endfunction
" These do not use quoting: `:Div foo bar baz` should work
command -nargs=* -range Div :call <SID>pdp_div(<line1>, <line2>, '-', <f-args>)
command -nargs=* -range Dive :call <SID>pdp_div(<line1>, <line2>, '=', <f-args>)
command -nargs=* -range Divt :call <SID>pdp_div(<line1>, <line2>, '~', <f-args>)
" 0x2500: ─, BOX DRAWINGS LIGHT HORIZONTAL ; 0x2501: ━, BOX DRAWINGS HEAVY HORIZONTAL
" 0x2704: ✄, WHITE SCISSORS
command -nargs=* -range Divh :call <SID>pdp_div(<line1>, <line2>, nr2char(0x2500, 1), <f-args>)
command -nargs=* -range DivH :call <SID>pdp_div(<line1>, <line2>, nr2char(0x2501, 1), <f-args>)
command -nargs=* -range Divhs :call <SID>pdp_div(<line1>, <line2>, '.'.nr2char(0x2704).'.'.nr2char(0x2500, 1), <f-args>)
command -nargs=* -range DivHs :call <SID>pdp_div(<line1>, <line2>, '.'.nr2char(0x2704).'.'.nr2char(0x2501, 1), <f-args>)
" This one requires quoting, first parameter (required) must be the
" separator; thus: `:Divx "~", "foo bar baz"`
" It's our escape hatch.
command -nargs=+ -range Divx :call <SID>pdp_div(<line1>, <line2>, <args>)
endif " has("eval")
@philpennock
Copy link
Copy Markdown
Author

Commit message from the git repo where this function canonically lives:

Overhaul vim :Div* commands

Intense dislike of the reversed ordering for :Divt finally crossed the
threshold for doing something about it.

Now have several commands, and only one still uses a quoted string:
:Divx takes the divider sequence first, per old :Divt, then takes
a single string which is the center tag. All the other functions use
<f-args> and the s:pdp_div() function joins all the arguments
after the separator on whitespace, such that you can do:
:Div foo bar baz and get 8< foo bar baz >8 as the heart of the
divider string. This should be much easier to use, once I unlearn the
habit of quoting args.

Modified the function to let the divider sequence look like .X.YYY
where X is a single (unicode) character and YYY is the separator
sequence as before. The X is then a line prefix.

Commands now: Divx Div Dive Divt Divh DivH Divhs DivHs

  • Divx is our escape hatch, two strings, must be fully quoted and
    comma-separated
  • Div is as before, but with simplified invocation as noted above
  • Dive with e for equals is the closest to our old Divt
  • Divt is t for tilde which looks unexpectedly nice (in my font)
  • Divh and DivH use box-drawing horizontals, light and heavy
  • Divhs and DivHs use the same box-drawings, but with WHITE SCISSORS
    at the start
-----------------------------8< cut here >8-----------------------------
=============================8< cut here >8=============================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~8< cut here >8~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
─────────────────────────────8< cut here >8─────────────────────────────
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━8< cut here >8━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✄────────────────────────────8< cut here >8─────────────────────────────
✄━━━━━━━━━━━━━━━━━━━━━━━━━━━━8< cut here >8━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

If I could reverse the scissors sanely, I'd try those bracketing the
label at the center. ☺️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment