5

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 <[email protected]>  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
  • 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, 2020 at 2:02

5 Answers 5

6

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 <[email protected]>  '
    \ . 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.

2
  • 2
    Excellent. That works. I setup my F5 key to do that. So much easier! :-) May 27, 2020 at 3:33
  • 3
    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, 2020 at 11:10
2

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 <[email protected]>  `!v strftime('%a, %d %b %Y %X %z')`
endsnippet

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.

8
  • I have some difficulties when it comes to too much automation, especially while I type. May 27, 2020 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, 2020 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 :-) May 27, 2020 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, 2020 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, 2020 at 13:07
1

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
2
  • Note that in case of a changelog, you only want to change that one line. Not all the dates in the file. What I first do is a Copy/Paste of the previous entry and then change the signature in the new entry. May 11, 2022 at 1:10
  • @AlexisWilke yes; you could omit the % in %subsitute and do something like yyp:Changed<CR>
    – D. Ben Knoble
    May 11, 2022 at 2:39
1

My two cents:

function! LogSignature() abort
    let firstname = "Alexis"
    let surname = "Wilke"
    let email = "<[email protected]>"
    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)
    else
        call append('.', signature)
    endif

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

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

4
  • 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, 2020 at 20:03
  • Oh. I should have thought more. This function is useless.
    – Biggybi
    May 27, 2020 at 20:09
  • 1
    It's great for e-mail messages though :-D
    – filbranden
    May 27, 2020 at 20:26
  • 1
    I updated it, now it's useful :D
    – Biggybi
    May 27, 2020 at 20:27
1

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 <[email protected]> - 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 <[email protected]> <Esc>

3
  • 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, 2020 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, 2020 at 20:02
  • @filbranden and D.Ben.Knoble thank you for your useful comments. I have updated my answer. May 28, 2020 at 19:13

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.