VIM: Enhancing focus on vim
Tags: vim, neovim
Published: 2022-03-21 11:18:06

---
title: VIM: Enhancing focus on vim
published: true
description: Some useful tips to keep your focus during writing on vim
tags: vim, neovim
---

## Keep your cursor in the middle of the screen in normal mode 

    :nnoremap j jzz
    :nnoremap k kzz

## Jump back 
As you know, vim has a jump list, and you can access previous jumping with <kbd>Ctrl</kbd><kbd>o</kbd> and use <kbd>Ctrl</kbd><kbd>i</kbd> to go to the newer positions on the jump list. 

Normally `j` and `k` do not change the jumplist but we can change this behavior:

    " source: https://www.vi-improved.org/vim-tips/
    nnoremap <expr> j v:count ? (v:count > 5 ? "m'" . v:count : '') . 'j' : 'gj'
    nnoremap <expr> k v:count ? (v:count > 5 ? "m'" . v:count : '') . 'k' : 'gk'

Now if you type `5j` your jump will be added to the jump list.

## Flash Cursorline Function
I am using lua to config my neovim and I have cursorline disabled. I have created a function to flash the cursorline and associate (map) it to some jumps:

```lua
-- ~/.config/nvim/lua/core/utils.lua
local M = {} -- M stands for module

-- https://vi.stackexchange.com/questions/31206
-- https://vi.stackexchange.com/a/36950/7339
M.flash_cursorline = function()
	local cursorline_state = lua print(vim.opt.cursorline:get())
    vim.opt.cursorline = true
    vim.cmd([[hi CursorLine guifg=#FFFFFF guibg=#FF9509]])
    vim.fn.timer_start(200, function()
        vim.cmd([[hi CursorLine guifg=NONE guibg=NONE]])
		if cursorline_state == false then
			vim.opt.cursorline = false
		end
    end)
end

-- map helper
M.map = function(mode, lhs, rhs, opts)
    local options = { noremap = true }
    if opts then
        options = vim.tbl_extend("force", options, opts)
    end
    vim.api.nvim_set_keymap(mode, lhs, rhs, options)
end

map('n', 'n', 'nzz:lua require("core.utils").flash_cursorline()<CR>Nn')
map('n', 'N', 'Nzz:lua require("core.utils").flash_cursorline()Beacon<CR>nN')

-- Why nzzNn: https://vi.stackexchange.com/a/36950/7339
-- zz will remove the count display ([n/nn]) in the statusbar if the view is changed. 
-- A quick and dirty solution to show the count again is to hit n or N again, ie.
-- nnoremap n nzzNn

map("n", "<C-o>", '<C-o>zv:lua require("core.utils").flash_cursorline()<CR>')
map("n", "<C-i>", '<C-i>zv:lua require("core.utils").flash_cursorline()<CR>')


return M
```

## Keep your cursor position during some actions:

To call any lua function we need to add our functions to a namespace and return this namespace, this means, at the beginning of the our module use:

```lua
M = {}
```

And at the end of it:

```lua
return M
```
Inside our module we add functions to this namesmapce prepending `M.` the the function we are creating.

```lua
-- file: ~/.config/nvim/lua/utils.lua
M.preserve = function(arguments)
    local arguments = string.format("keepjumps keeppatterns execute %q", arguments)
    -- local original_cursor = vim.fn.winsaveview()
    local line, col = unpack(vim.api.nvim_win_get_cursor(0))
    vim.api.nvim_command(arguments)
    local lastline = vim.fn.line("$")
    -- vim.fn.winrestview(original_cursor)
    if line > lastline then
        line = lastline
    end
    vim.api.nvim_win_set_cursor(0, { line, col })
end
```

You can use the above function this way:

```lua
-- dos2unix
M.dosToUnix = function()
    M.preserve("%s/\\%x0D$//e")
    vim.bo.fileformat = "unix"
    vim.bo.bomb = true
    vim.opt.encoding = "utf-8"
    vim.opt.fileencoding = "utf-8"
end
vim.cmd([[command! Dos2unix lua require('core.utils').dosToUnix()]])
```

The command outside the Dos2unix function creates a command that calls the function, of course you also can create mappings to do the same.

Reduce to or more spaces to one keeping the cursor position:

```lua
M.squeeze_blank_lines = function()
-- references: https://vi.stackexchange.com/posts/26304/revisions
	if vim.bo.binary == false and vim.opt.filetype:get() ~= "diff" then
		local old_query = vim.fn.getreg("/") -- save search register
		M.preserve("sil! 1,.s/^\\n\\{2,}/\\r/gn") -- set current search count number
		local result = vim.fn.searchcount({ maxcount = 1000, timeout = 500 }).current
		local line, col = unpack(vim.api.nvim_win_get_cursor(0))
		M.preserve("sil! keepp keepj %s/^\\n\\{2,}/\\r/ge")
		M.preserve("sil! keepp keepj %s/^\\s\\+$/\\r/ge")
		M.preserve("sil! keepp keepj %s/\\v($\\n\\s*)+%$/\\r/e")
		if result > 0 then
			vim.api.nvim_win_set_cursor(0, { (line - result), col })
		end
		vim.fn.setreg("/", old_query) -- restore search register
	end
end
```

Change the "Last Change: dd/mm/yy" at the begining of your file each time you save it (it needs an autocommand for it):

```lua
--> :lua changeheader()
-- This function is called with the BufWritePre event (autocmd)
-- and when I want to save a file I use ":update" which
-- only writes a buffer if it was modified
M.changeheader = function()
    -- We only can run this function if the file is modifiable
    if not vim.api.nvim_buf_get_option(vim.api.nvim_get_current_buf(), "modifiable") then
        return
    end
    if vim.fn.line("$") >= 7 then
        os.setlocale("en_US.UTF-8") -- show Sun instead of dom (portuguese)
        time = os.date("%a, %d %b %Y %H:%M")
        M.preserve("sil! keepp keepj 1,7s/\\vlast (modified|change):\\zs.*/ " .. time .. "/ei")
    end
end
```

To see an autocmd.lua file you can follow [this link](https://dev.to/voyeg3r/my-ever-growing-neovim-init-lua-h0p).

We can even reindent the whole file keeping the cursor position:

```lua
vim.cmd([[command! Reindent lua require('core.utils').preserve("sil keepj normal! gg=G")]])
```
## Jump to the alternate file:

When you have the buffer list opened it will be like this:

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9pc0eoal85fapglm59cs.png)

To alternate between the current file and the alternate file, wich is the last one you were on, just press `Ctrl-6`