3

Currently I’m adding source sections manually, e.g.:

/*******************************************************************************
 *                                entry point
 ******************************************************************************/
fn main () { println!("Hello World!"); }

The commands required to create this particular heading is quite long:

0a*<ESC>oentry point<ESC>:ce<CR>kYjpr $r/kk0r/jl

For languages only supporting line comments the sequence is a bit shorter.

Once I have an initial section, I simply copy and paste it to create all subsequent ones, which reduces the effort to find some header, past it to where I need it, replace the label text, and re-center it.

What would be a less pedestrian way to achieve this?

Sectioning should employ the current comment character settings of the Nerd Commenter plugin. Supplying their own list would be fine too.

No language specific plugins please.

10
  • 10
    Don't do that: your code doesn't need it and only create useless stuff which harden the reading. If you still really want to do that, check a snippet manager plugin. Also not a duplicate but a strongly related question
    – statox
    Jul 4, 2016 at 10:01
  • 1
    Also see: making a box using vimscript-python: vi.stackexchange.com/a/585/205
    – muru
    Jul 4, 2016 at 10:32
  • 4
    A pedestrian way would be to solve the problem for a given language first. As the pedestrian learns to mount VimL horses, he might evolve the solution by looking at &comments and &textwidth to make it language-independent (when possible, that is). Jul 4, 2016 at 12:49
  • 1
    @phg: I agree with statox on this one. It does not add any meaning to the file, only a visual mark of something important. If a first time reader need to go through a file for the first time, it may rely on classes, functions, namespaces (depending on the languages). Those are useful for the program to run and for the reader to understand. If you find it hard to understand a commented code, you may want to try with a generated documentation, which purpose is to be read instead to grasp the purpose of the code.
    – nobe4
    Jul 4, 2016 at 13:34
  • 1
    @phg I meant to add "for purpose specific code", like "text utilities" and "image processing" if they have to be in the same file. I also said I use a single line with a searchable prefix, like //// text utilities. Your example looks like you want function banners.
    – Tommy A
    Jul 4, 2016 at 14:59

5 Answers 5

8

Note 1 As I said in the comment this kind of box is not a good thing: it distract the eye from the important part of your file (the comment itself or the actual code). There are better way to create headers. Now this is only my opinion and this site is not here to argue about this so here is a solution.

Note 2 I give here a solution with the plugins I know but you could probably use any snippet manager other than Ultisnips.

Note 3 Using a snippet manager only for this snippet is probably overkill and you should probably considering creating your own vimscript function. For example, here is an answer I made (with a great help from @Peter Rincker) for a similar question. It uses only vimscript and creates headers a little lighter.


What you are looking for is an intelligent snippet, it is also a built-in feature of Ultisnips + vim-snippets:

First, install ultisnips which is a snippet engine (it will allow you to work with snippets but doesn't provide the snippets themselves).

Then you have two ways to get the snippet you're looking for:

Method 1 You can install vim-snippets which provides a whole list of predefined snippets.

Method 2 You can declare the snippet by yourself (which is a little bit more work but is lighter since you get only the snippet you need):

First create a file ~/.vim/my-snippets/Ultisnips/all.snippets.

Then in this file add this:

global !p
def make_box(twidth, bwidth=None):
    b, m, e, i = (s.strip() for s in get_comment_format())
    bwidth_inner = bwidth - 3 - max(len(b), len(i + e)) if bwidth else twidth + 2
    sline = b + m + bwidth_inner * m[0] + 2 * m[0]
    nspaces = (bwidth_inner - twidth) // 2
    mlines = i + m + " " + " " * nspaces
    mlinee = " " + " "*(bwidth_inner - twidth - nspaces) + m
    eline = i + m + bwidth_inner * m[0] + 2 * m[0] + e
    return sline, mlines, mlinee, eline

def get_comment_format():
    """ Returns a 4-element tuple (first_line, middle_lines, end_line, indent)
    representing the comment format for the current file.

    It first looks at the 'commentstring', if that ends with %s, it uses that.
    Otherwise it parses '&comments' and prefers single character comment
    markers if there are any.
    """
    commentstring = vim.eval("&commentstring")
    if commentstring.endswith("%s"):
        c = commentstring[:-2]
        return (c, c, c, "")
    comments = _parse_comments(vim.eval("&comments"))
    for c in comments:
        if c[0] == "SINGLE_CHAR":
            return c[1:]
    return comments[0][1:]
endglobal

snippet box "A nice box with the current comment symbol" b
`!p
box = make_box(len(t[1]))
snip.rv = box[0]
snip += box[1]
`${1:content}`!p
box = make_box(len(t[1]))
snip.rv = box[2]
snip += box[3]`
$0
endsnippet

The part in the global/endglobal are python helper function made to create a box and get the comment character for the buffer. The part in the snippet/endsnippet is the actual snippet using the python interpolations.

Then independently from the method you followed, you simply have to type box and then use the key you defined in your vimrc to trigger a snippet and the box will be created. You'll then enter insert mode allowing you to type the text you want to put in a box, the length of the box will be updated while you enter the text.

Note that I didn't create the code in this answer, it comes directly from the vim-snippets directory here and here


Some interesting resources about snippets:

  • I asked a question to differentiate the different snippets managers. As long as you choose snipmate compatible snippets engines, the one I gave you should work.
  • Vimcast made some good episodes about Ultisnips.
  • And of course the ultisnip doc is a good place to start.
7

I actually wrote a blog post about this:

http://rainymood.github.io/jekyll/update/2016/06/25/vim-macro.html

tl;dr use a Vim Macro

Macro used for the image below

qai###<Esc>A<Esc><Space>###<Esc>YppkkVR#jjVR#q

image

You could probably do something similar

3
  • This doesn’t expand to textwidth for one. Also, seems like it’s quite language specific
    – phg
    Jul 4, 2016 at 11:22
  • 2
    @phg You're trying too hard to make the problem a pain in the rear for the potential answerers. Jul 4, 2016 at 12:40
  • 2
    @phb you are correct. I have to note that I never said it would expand to textwidth. I merely wanted to show a solution that I hacked together which I think might solve OP's problem fairly quickly (i.e. simple use of a vim macro)
    – Rainymood
    Jul 4, 2016 at 12:45
4

!!boxes

Another solution is filtering the line through the command line tool (ascii-)boxes

!!boxes -s 72 -d c

or use visual selection

'<,'>!boxes -s 72 -d c 
  • -s 72 size of box
  • -d c select box type (design); here the c box; to see box designs run $ boxes -l

boxes can be installed via homebrew/linuxbrew and linux distro packages, e.g. debian (https://packages.debian.org/jessie/boxes) and ubuntu (http://packages.ubuntu.com/yakkety/boxes).

Note
However, I agree boxes can reduce code readability. Use them wisely.

2
  • boxes looks really great, thanks for the recommendation. However, despite its comprehensive website and manpage I couldn’t make it accept a triple of strings---start, middle, end---to create the box. Also, to use it in a sufficiently flexible manner one would still have to pass it the info in Vim’s comments variable in some fashion (via custom box designs, most likely). So IMO it doesn’t beat drawing those boxes with a plugin.
    – phg
    Jul 6, 2016 at 11:22
  • The author of boxes has created a Text Editor integration website. There are given mappings for certain FileType events with a common keybinding. If all design names are chose accordingly to filetype names, this could be simplified, also optionally incorporating the value from &textwidth.
    – Hotschke
    Jul 6, 2016 at 12:25
2

I wrote a little script, to block the selected texts with customized characters. well it is not yet valid C/java comment, however it shouldn't be hard to adjust. Take a look if it helps:

https://github.com/sk1418/blockit

the Readme includes gif animation and introductions.

0

Came up with my own script: https://gist.github.com/anonymous/7878a79fccc74bbc00db6cf0c330c23f

It parses &comments to generate a formatted block with separators expanded to &textwidth. By default, Leaderh inserts the block while in insert and normal mode.

Since comments is a bit weird to process, the script will output garbage for certain values. But it’s been tweaked enough to work for the ones that matter to me personally.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.