Whenever I make an update to the changelog of a Debian package, I have to update the signature with the correct date (well, it's not mandatory, but it's really nice to have).

The signature looks like this:

 -- Alexis Wilke <alexis@example.com>  Tue, 26 May 2020 18:00:09 -0800

I'd like to have a command in [g]vim that would replace a signature with my signature and the correct date and time. It's annoying to have to update the date by hand each time, and it is prone to mistakes (i.e. Mom, 18000:09, Jum, etc.) and when Launchpad detects an error it just stops right there.

So having a way to auto-update these signatures would be marvelous.

Do you have such a function or do you know how to write one? In the end, I ideally just have to hit one key and it happens: replacement of the entire line with my signature and the current date in the exact same format.

  • 1
    It should be fairly easy to write a function to automate this. On the same principle as signatures, this article shows how to make custom headers. I'll try to craft something tomorrow if there's no answer until then. – Biggybi May 27 at 2:02

Here's a simple, somewhat dumb solution, that doesn't require any plug-ins or anything.

Just add this snippet to your vimrc:

iabbrev <expr> debsig
    \ ' -- Alexis Wilke <alexis@example.com>  '
    \ . strftime('%a, %d %b %Y %H:%M:%S %z')

This creates an "abbreviation", which you can later invoke by typing debsig and then pressing return or another whitespace. (You can also use Ctrl-] to expand the abbreviation without inserting any extra whitespace.)

This is hardcoding your name and e-mail instead of finding them out (for instance, from Vim config), but it should get the date right, which should be the important part here...

Of course, feel free to customize the debsig trigger to anything you prefer. If you prefer to use a Ctrl+key combination or F-key, then use inoremap instead of iabbrev.

| improve this answer | |
  • 2
    Excellent. That works. I setup my F5 key to do that. So much easier! :-) – Alexis Wilke May 27 at 3:33
  • 2
    As a bonus: stftime() actually supports raw text, so you could do it all in one single line. I would also concatenate the strings for this case, but you could do something like strftime('-- Tim Berners-Lee, %c') to sign off with the current locale's datetime. Check LC_TIME, LC_ALL, LANG for %c. – mazunki May 27 at 11:10

You can also use snippet plugin such as ultisnips to achieve this. Just write a short snippet for it. For how to configure ultisnips, see this post.

You need to create a file named debchangelog.snippets in the custom snippet directory and add the following snippet into it:

snippet debsig "debian change log signature" w
-- Alexis Wilke <alexis@example.com>  `!v strftime('%a, %d %b %Y %X %z')`

The backticked text use the interpolation feature of Ultisnips. !v means to use Vim language interpolation, and it should be followed by valid Vim script expressions, like the one given above.

After adding this snippet, when you open a debian changelog file[^1], type debsig and press the trigger key, it will be expanded to the signature automatically.

enter image description here

[^1]: Make sure that the filetype is debchangelog, otherwise set the filetype to debchangelog manually.

| improve this answer | |
  • I have some difficulties when it comes to too much automation, especially while I type. – Alexis Wilke May 27 at 6:03
  • The snippet will not expand automatically, you need to press a trigger key for it. The iabbrev way is like auto-expansion. – jdhao May 27 at 6:06
  • I actually used a map <F5> ..., I just hit F5 on that line and the whole line is replaced with my signature. It's really cool :-) – Alexis Wilke May 27 at 6:24
  • Yes, I really think a snippet manager is the right answer for this and UltiSnips is probably the one most available these days. But I think this answer could be improved significantly by actually providing an actual snippet that can be used for this specific purpose. Would you be willing to write one? – filbranden May 27 at 12:56
  • 1
    @filbranden Yes, I am writing one and will post it here once I have tested it for its correctness. – jdhao May 27 at 13:07

I have this command in my vimrc which you can tweak to get your exact text; then I do :Changed and it updates all the timestamps in the current file:

command Changed keeppatterns %substitute/Last [cC]hanged\?:\zs.*/\=strftime(" %Y %b %d")/e
| improve this answer | |
  • +1 for the elegant substitution – Biggybi May 27 at 19:40

My two cents:

function! LogSignature() abort
    let firstname = "Alexis"
    let surname = "Wilke"
    let email = "<alexis@example.com>"
    let prefix = " --"

    let signature_undated = prefix . " " . firstname . " " . surname . " " . email
    let signature = signature_undated . " " . strftime('%a, %d %b %Y %H:%M:%S %z')

    "update or insert signature
    if getline('.') =~ '^.*'.signature_undated
        call setline('.', signature)
        call append('.', signature)

nnoremap <F5> :call LogSignature()<cr>

If you launch the function on the line where a signature is already present, it will be updated.

| improve this answer | |
  • On a Debian changelog, the signature is not really the last line of the file, rather you add a block at the top with the changes to the latest version and you add a signature at the end of that block. So typically you'll add it somewhere at the top of the file. See this changelog for an example. – filbranden May 27 at 20:03
  • Oh. I should have thought more. This function is useless. – Biggybi May 27 at 20:09
  • 1
    It's great for e-mail messages though :-D – filbranden May 27 at 20:26
  • 1
    I updated it, now it's useful :D – Biggybi May 27 at 20:27

I think the best way to do it use a macro. Macros allow you to record your key-strokes and saves them. Macros are persistent across vim sessions.

You can store your macro in the letter s for signature.

The way I would do is:

  1. qs - start recording the macro and store it in letter s
  2. i - go into insert mode
  3. -- Alexis Wilke <alexis@example.com> - you will have to type this manually
  4. <Esc> - exit insert mode
  5. :read !date - this command will read the time from bash built-in
  6. q - stop recording the macro

Now, you can use your macro using @s. Now, the important thing to remember is that this macro can be overwritten. So, don't use this macro key for anything else.

If you are looking for a more permanent solution, you can map it a key like this:

:nnoremap <leader>s :.!date -R<CR>I-- Alexis Wilke <alexis@example.com> <Esc>

| improve this answer | |
  • 1
    Welcome to Vi and Vim! You might consider using nnoremap to avoid recursive mappings, since you don't need them here. – D. Ben Knoble May 27 at 18:29
  • Also, the date format is an important part of this, if you use the external date, you should use date -R instead to generate it in the appropriate format... – filbranden May 27 at 20:02
  • @filbranden and D.Ben.Knoble thank you for your useful comments. I have updated my answer. – Tejas Sanap May 28 at 19:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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