• Stars
    star
    501
  • Rank 88,002 (Top 2 %)
  • Language
    Lua
  • Created almost 4 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Auto-Focusing and Auto-Resizing Splits/Windows for Neovim written in Lua. A full suite of window management enhancements. Vim splits on steroids!

focus.nvim

GitHub stars Requires Neovim 0.7+ GitHub contributors PRs Welcome GitHub issues GitHub issues-closed

Always have a nice view over your split windows

Preview

screencast

Note: For reference this screencast features dimensions set to 40 rows and 120 columns.

See a visual demonstration of each focus feature here.

Features

  • 👌 Resizes split windows automatically based on golden ratio
  • ⚙️ Enables cursorline/signcolumn/numbers on focus window only
  • 🙌 Window creation or switch by direction
  • 🖥 Equalise splits or maximise focused splits, and toggle between the two
  • 🔌 Option to open tmux windows instead of creating new splits

Installation

Here are code snippets for some common installation methods (use only one):

With folke/lazy.nvim
Github repo Branch Code snippet
'focus.nvim' library Main { 'nvim-focus/focus.nvim', version = false },
Stable { 'nvim-focus/focus.nvim', version = '*' },
With wbthomason/packer.nvim
Github repo Branch Code snippet
'focus.nvim' library Main use 'nvim-focus/focus.nvim'
Stable use { 'nvim-focus/focus.nvim', branch = 'stable' }
With junegunn/vim-plug
Github repo Branch Code snippet
'focus.nvim' library Main Plug 'nvim-focus/focus.nvim'
Stable Plug 'nvim-focus/focus.nvim', { 'branch': 'stable' }

Configuration

For basic setup with all batteries included:

require("focus").setup()

Configuration can be passed to the setup function. Here is an example with the default settings:

require("focus").setup({
    enable = true, -- Enable module
    commands = true, -- Create Focus commands
    autoresize = {
        enable = true, -- Enable or disable auto-resizing of splits
        width = 0, -- Force width for the focused window
        height = 0, -- Force height for the focused window
        minwidth = 0, -- Force minimum width for the unfocused window
        minheight = 0, -- Force minimum height for the unfocused window
        height_quickfix = 10, -- Set the height of quickfix panel
    },
    split = {
        bufnew = false, -- Create blank buffer for new split windows
        tmux = false, -- Create tmux splits instead of neovim splits
    },
    ui = {
        number = false, -- Display line numbers in the focussed window only
        relativenumber = false, -- Display relative line numbers in the focussed window only
        hybridnumber = false, -- Display hybrid line numbers in the focussed window only
        absolutenumber_unfocussed = false, -- Preserve absolute numbers in the unfocussed windows

        cursorline = true, -- Display a cursorline in the focussed window only
        cursorcolumn = false, -- Display cursorcolumn in the focussed window only
        colorcolumn = {
            enable = false, -- Display colorcolumn in the foccused window only
            list = '+1', -- Set the comma-saperated list for the colorcolumn
        },
        signcolumn = true, -- Display signcolumn in the focussed window only
        winhighlight = false, -- Auto highlighting for focussed/unfocussed windows
    }
})

Setup options

Enable/Disable Focus

-- Completely disable this plugin
-- Default: true
require("focus").setup({enable = false})

Enable/Disable Focus Commands

-- This not export :Focus* commands
-- Default: true
require("focus").setup({commands = false})

Enable/Disable Focus Window Autoresizing

--The focussed window will no longer automatically resize. Other focus features are still available
-- Default: true
require("focus").setup({ autoresize = { enable = false } })

Set Focus Width

-- Force width for the focused window
-- Default: Calculated based on golden ratio
require("focus").setup({ autoresize = { width = 120 } })

Set Focus Minimum Width

-- Force minimum width for the unfocused window
-- Default: Calculated based on golden ratio
require("focus").setup({ autoresize = { minwidth = 80} })

Set Focus Height

-- Force height for the focused window
-- Default: Calculated based on golden ratio
require("focus").setup({ autoresize = { height = 40 } })

Set Focus Minimum Height

-- Force minimum height for the unfocused window
-- Default: 0
require("focus").setup({ autoresize = { minheight = 10} })

Set Focus Quickfix Height

-- Sets the height of quickfix panel, in case you pass the height to
-- `:copen <height>`
-- Default: 10
require("focus").setup({ autoresize = { height_quickfix = 10 })

When creating a new split window, do/don't initialise it as an empty buffer

-- True: When a :Focus.. command creates a new split window, initialise it as a new blank buffer
-- False: When a :Focus.. command creates a new split, retain a copy of the current window in the new window
-- Default: false
require("focus").setup({ split = { bufnew = true } })

Set Focus Auto Numbers

-- Displays line numbers in the focussed window only
-- Not displayed in unfocussed windows
-- Default: true
require("focus").setup({ui = { number = false } })

Set Focus Auto Relative Numbers

-- Displays relative line numbers in the focussed window only
-- Not displayed in unfocussed windows
-- See :help relativenumber
-- Default: false
require("focus").setup({ ui = { relativenumber = true } })

Set Focus Auto Hybrid Numbers

-- Displays hybrid line numbers in the focussed window only
-- Not displayed in unfocussed windows
-- Combination of :help relativenumber, but also displays the line number of the
-- current line only
-- Default: false
require("focus").setup({ ui = { hybridnumber = true} })

Set Presrve Absolute Numbers

-- Preserve absolute numbers in the unfocussed windows
-- Works in combination with relativenumber or hybridnumber
-- Default: false
require("focus").setup({ ui = { absolutenumber_unfocussed = true } })

When creating a new split window, use tmux split instead of neovim

-- True: Create tmux splits instead of neovim splits
-- False: Create neovim split windows
-- Default: false
require("focus").setup({ split = { tmux = true } })

Set Focus Auto Cursor Line

-- Displays a cursorline in the focussed window only
-- Not displayed in unfocussed windows
-- Default: true
require("focus").setup({ ui = { cursorline = false } })

Set Focus Auto Cursor Column

-- Displays a cursor column in the focussed window only
-- See :help cursorcolumn for more options
-- Default: false
require("focus").setup({ ui = { cursorcolumn = true } })

Set Focus Auto Color Column

-- Displays a color column in the focussed window only
-- See :help colorcolumn for more options
-- Default: enable = false, list = '+1'
require("focus").setup({
    ui = {
        colorcolumn = {
            enable = true,
            list = '+1,+2'
        }
    }
})

Set Focus Auto Sign Column

-- Displays a sign column in the focussed window only
-- Gets the vim variable setcolumn when focus.setup() is run
-- See :help signcolumn for more options e.g :set signcolum=yes
-- Default: true, signcolumn=auto
require("focus").setup({ ui = { signcolumn = false } })

Set Focus Window Highlighting

-- Enable auto highlighting for focussed/unfocussed windows
-- Default: false
require("focus").setup({ ui = { winhighlight = true } })

-- By default, the highlight groups are setup as such:
--   hi default link FocusedWindow VertSplit
--   hi default link UnfocusedWindow Normal
-- To change them, you can link them to a different highlight group, see
-- `:help hi-default` for more info.
vim.highlight.link('FocusedWindow', 'CursorLine', true)
vim.highlight.link('UnfocusedWindow', 'VisualNOS', true)

Disabling Focus

Focus can be disabled by setting a variable for a buffer (vim.b.focus_disable = true) or globally (vim.b.focus_disable = true).

If you want to disable Focus for certain buffer or file types you can do this by setting up autocommands (:help autocmd) in your configuration.

Here is an example:

local ignore_filetypes = { 'neo-tree' }
local ignore_buftypes = { 'nofile', 'prompt', 'popup' }

local augroup =
    vim.api.nvim_create_augroup('FocusDisable', { clear = true })

vim.api.nvim_create_autocmd('WinEnter', {
    group = augroup,
    callback = function(_)
        if vim.tbl_contains(ignore_buftypes, vim.bo.buftype) then
            vim.b.focus_disable = true
        end
    end,
    desc = 'Disable focus autoresize for BufType',
})

vim.api.nvim_create_autocmd('FileType', {
    group = augroup,
    callback = function(_)
        if vim.tbl_contains(ignore_filetypes, vim.bo.filetype) then
            vim.b.focus_disable = true
        end
    end,
    desc = 'Disable focus autoresize for FileType',
})

Vim Commands

For more information on below commands scroll down to see them each described in more detail

Command Description
:FocusDisable Disable the plugin per session. Splits will be normalized back to defaults and then spaced evenly.
:FocusEnable Enable the plugin per session. Splits will be resized back to your configs or defaults if not set.
:FocusToggle Toggle focus on and off again.
:FocusSplitNicely Split a window based on the golden ratio rule.
:FocusSplitCycle If there are no splits, create one and move to it, else cycle focussed split. :FocusSplitCycle reverse for counterclockwise
:FocusDisableWindow Disable resizing of the current window (winnr).
:FocusEnableWindow Enable resizing of the current window (winnr).
:FocusToggleWindow Toggle focus on and off again on a per window basis.
:FocusGetDisabledWindows Pretty prints the list of disabled window ID's along with the current window ID.
:FocusSplitLeft Move to existing or create a new split to the left of your current window + open file or custom command.
:FocusSplitDown Move to existing or create a new split to the bottom of your current window + open file or custom command.
:FocusSplitUp Move to existing or create a new split to the top of your current window + open file or custom command.
:FocusSplitRight Move to existing or create a new split to the right of your current window + open file or custom command.
:FocusEqualise Temporarily equalises the splits so they are all of similar width/height.
:FocusMaximise Temporarily maximises the focussed window.
:FocusMaxOrEqual Toggles Between having the splits equalised or the focussed window maximised.

Splitting Nicely

Focus allows you to split windows to tiled windows nicely and sized according to the golden ratio.

+----------------+------------+
|                |    S1      |
|                |            |
|                +------------+
|                |            |
|   MAIN PANE    |    S2      |
|                |            |
|                |            |
|                |            |
+----------------+------------+

To get this view you would press the key combination 2 times.

Split nicely with <C-l>

keymap('n', '<c-l>', function()
    require('focus').split_nicely()
end, { desc = 'split nicely' })

Additionally you can open a file or a run a custom command with the :FocusSplitNicely command

Opens a file in the split created by FocusSplitNicely command

:FocusSplitNicely README.md

Opens a terminal window in the split created by FocusSplitNicely command by using the cmd arg to run a custom command

:FocusSplitNicely cmd term

Split directionally

Instead of worrying about multiple commands and shortcuts, simply think about splits as to which direction you would like to go.

Calling a focus split command i.e :FocusSplitRight will do one of two things, it will attempt to move across to the window in the specified direction. Otherwise, if no window exists in the specified direction relative to the current window then it will instead create a new blank buffer window in the direction specified, and then move to that window.

Leverage hjkl to move or create your splits directionally

local focusmap = function(direction)
    vim.keymap.set('n', '<Leader>'..direction, function()
        require('focus').split_command(direction)
    end, { desc = string.format('Create or move to split (%s)', direction) })
end

-- Use `<Leader>h` to split the screen to the left, same as command FocusSplitLeft etc
focusmap('h')
focusmap('j')
focusmap('k')
focusmap('l')

Additionally you can open a file or a run a custom command with the :FocusSplit<direction> command

Opens a file in a split that was either created or moved to

:FocusSplitRight README.md

Opening a terminal window by using the cmd arg to run a custom command in a split that was created or moved to

:FocusSplitDown cmd term

FAQ

  • I have a small display and I am finding splits are resized too much

    If for example your screen resolution is 1024x768 --> i.e on the smaller side, you may notice that focus by default can maximise a window too much.

    That is, the window will sort of 'crush' some of your other splits due to the limited screen real estate. This is not an issue with focus, but an issue with minimal screen real estate. In this case, you can simply reduce the width/height of focus.

  • Quickfix window opens in the right split always. Is this caused by focus.lua?

    No. This is a documented design decision by core vim, this might be something that can be adjusted upstream.

    In the meantime, you can open a quickfix window occupying the the full width of the window with :botright copen

  • I tried to lazy load focus with :FocusToggle, but I need to toggle it again to get auto-resizing working

    Please note if you lazy load with command :FocusToggle, it will load focus, but will toggle it off initially. See #34.

    This is because focus is toggled on by default when you load focus, so if you load it and then run the command :FocusToggle, it toggles it off again.

Similar plugins

Developers Only

Contributing

Please before submitting a PR install stylua and run it in the root folder of focus.nvim.

stylua .

This will format the code according to the guidelines set in .stylua.toml.

Testing

You can run the tests using make test if you initialise the git submodules.

More Repositories

1

statusline.lua

A zero-config minimal statusline for neovim written in lua featuring awesome integrations and blazing speed!
Lua
198
star
2

Dotfiles

Well documented awesome dotfiles 😍 Many neovim lua configs, handy zsh/bash functions, fzf functions + more
Lua
76
star
3

awesome-fzf

A community repo of fzf scripts and awesome functions 😍
Shell
75
star
4

imnotaquitter.vim

Don't be a quitter. Be a real one.
Vim Script
21
star
5

nx-monorepo-full-stack-app

Modern monorepo full stack app based on the typestack. E2E Code gen of types.
TypeScript
18
star
6

demo-next-typescript-hardhat-marketplace

A full stack NFT marketplace. Aiming for clean and cocise code that is easy to understand + rock solid setup scripts & other automations to speed up development.
TypeScript
18
star
7

Vimage

Automated neovim development environment container for developers supporting many languages. Simply run the script and begin coding with a fully configured neovim. Including my dotfile configurations.
Dockerfile
8
star
8

AutoWrite.vim

Simple AutoWrite Plugin compatible with most if not all vim distributions (Vim/Neovim)
Vim Script
5
star
9

flatbox

Lua
4
star
10

fzf-cheat.sh

The ultimate cheat.sh wrapper leveraging fzf
Shell
4
star
11

Solidity-Hardhat-Starter-Template

A comprehensive starter template for solidity based on hardhat framework. Auditing/Test CI, Tasks, Upgradeable Contract & More
TypeScript
3
star
12

MSA-AUS-2020-FlaskWebsite

Website/Slides for my Demo for Microsoft Student Accelerator Web Dev and API Workshop
HTML
3
star
13

Solidity-Multichain-Deployments-Shared-Address

Deploy contracts on multiple chains, using a pre-determined address using CREATE2 EVM opcode. Shared address across multiple chains.
TypeScript
3
star
14

AuthUpgradeable-abstract-contract-solidity

A simple upgradeable solidity smart contract to authorise certain wallets in a list to access certain functions, retaining onlyOwner functionality
TypeScript
2
star
15

Alfred-System-Media-Controller

Easily Control Media On Your Mac, System Wide!
2
star
16

awesome-hardhat

Awesome list of Hardhat plugins, resources and more.
1
star
17

blog.beauwilliams.dev

1
star
18

fzf-scratch

A searchable list of scratch notes leveraging fzf. Create notes on the fly. Keeps your notes in one place. No need to leave your current directory.
Shell
1
star
19

NFT20

NFT20 is the metacurrency of the metaverse. Behold, NFTs as wallets.
Solidity
1
star
20

Alfred-Logitech-Mouse-Daemon-Killer

Quickly kill & restart a frozen logitech mouse daemon (MacOS)
1
star
21

Forge-NX-Demo

Forge-NX-Demo
TypeScript
1
star
22

THC_NAZA_NFT_Contract

Solidity
1
star
23

EllipticCurve-Secp256k1-Secret-Sharing

EllipticCurve-Secp256k1-Secret-Sharing
Go
1
star
24

MSA-AUS-2020-AzureML

I developed and ran a demo and coding competition for the Microsoft Student Accelerator program where students learnt about AI/ML. This is a live coding demo of MNIST image rec project.
HTML
1
star
25

Cygorithm_THC_NAZA_Dropsite

CSS
1
star
26

Git-Workshop

A Git Workshop --> Hosted by Australian Google DSC Clubs
HTML
1
star
27

Vanilla-Typescript-API

TypeScript
1
star