DEV Community

Sérgio Araújo
Sérgio Araújo

Posted on • Updated on

Neovim "Last Change" function

Currently I am using a git hook to update file headings:

https://dev.to/voyeg3r/update-your-files-header-using-git-hooks-460c

Update the line "Last Change" each time your file is saved

I love the level of automation that vim/neovim allows us to achieve, just for give you an example, I have the following function in my ~/.config/nvim/lua/core/utils.lua

-- ~/.config/nvim/lua/core/utils.lua

local M = {}

M.changeheader = function()
    -- We only can run this function if the file is modifiable
    local bufnr = vim.api.nvim_get_current_buf()
    if not vim.api.nvim_buf_get_option(bufnr, "modifiable") then
        require("notify")("Current file not modifiable!")
        return
    end
    -- if not vim.api.nvim_buf_get_option(bufnr, "modified") then
    --     require("notify")("Current file has not changed!")
    --     return
    -- end
    if vim.fn.line("$") >= 7 then
    os.setlocale("en_US.UTF-8") -- show Sun instead of dom (portuguese)
    local time = os.date("%a, %d %b %Y %H:%M:%S")
    local l = 1
    while l <= 7 do
        vim.fn.setline(l, vim.fn.substitute(vim.fn.getline(l), 'last change: \\zs.*', time , 'gc'))
        l = l + 1
    end
       if vim.fn.search('\\vlast (change|update):?', 'wncp') > 0 then
            require("notify")("Changed file header!")
       end
    end
end

return M
Enter fullscreen mode Exit fullscreen mode

The function is triggered in the autocommands file:

local augroups = {}

augroups.misc = {
    change_header = {
        event = "BufWritePre",
        pattern = "*",
        callback = function()
            require('core.utils').changeheader()
        end,
    },
}

for group, commands in pairs(augroups) do
    local augroup = vim.api.nvim_create_augroup("AU_"..group, {clear = true})

    for _, opts in pairs(commands) do
        local event = opts.event
        opts.event = nil
        opts.group = augroup
        vim.api.nvim_create_autocmd(event, opts)
    end
end
Enter fullscreen mode Exit fullscreen mode

The great advantage of using the function substitute() along with setline() is that your changelist and your jumplist will not be changed.

Tips about keeping your files timestamp

When copying files on Linux use the option -p, "preserve" to keep the timestamp.

I have a bunch of files in my personal wiki where I wanted to fix the "Last Change:" line, about 600 files. I used this script to fix the issue:

(
cd ~/.dotfiles/wiki || exit
for file in *.md; do
    echo "Modificando o arquivo $file .."
    t=$(stat -c "%y" "$file") # original timestamp
    new_date=$(date -r "$file" +'%a, %d %b %Y - %H:%M:%S')
    sed -i "1,7s/\(Last Change: \).*/\1 $new_date/g" "$file"
    # sed -i '1,7{/^[Cc]reated:/d}' "$file" # in this case delete lines with pattern
    touch -d "$t" "$file"
done
)
Enter fullscreen mode Exit fullscreen mode

Basically:

1 - Store the timestamp in a variable
2 - Use date -r to get a string to use in sed
3 - Use sed to change the line "Last Change:"
4 - Restore the timestamp using the variable from the step 1

Top comments (1)

Collapse
 
voyeg3r profile image
Sérgio Araújo

I have just added a test, just in case the file does not have "Last Change/Update" on it the message does not appear.