Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/chimay/wheel

Any line in any file is only a few keys away. Quick navigation for Vim and Neovim : file groups, buffers, find, grep/edit, mru, frecency, sessions, yank, ...
https://github.com/chimay/wheel

find frecency grep group history navigation neovim refactor search session tabs-wins vim yankring

Last synced: about 2 months ago
JSON representation

Any line in any file is only a few keys away. Quick navigation for Vim and Neovim : file groups, buffers, find, grep/edit, mru, frecency, sessions, yank, ...

Awesome Lists containing this project

README

        

* [Introduction](#introduction)
* [What is it ?](#what-is-it-)
* [What does it look like ?](#what-does-it-look-like-)
* [History and meta-command](#history-and-meta-command)
* [Frecency, dedicated buffers and layers](#frecency-dedicated-buffers-and-layers)
* [More screenshots & screencasts](#more-screenshots--screencasts)
* [File groups & categories](#file-groups--categories)
* [Why do you need three levels of grouping ?](#why-do-you-need-three-levels-of-grouping-)
* [A wheel that follows you](#a-wheel-that-follows-you)
* [Features](#features)
* [History](#history)
* [Prerequisites](#prerequisites)
* [Software](#software)
* [Operating system](#operating-system)
* [Installation](#installation)
* [Using vim-packager](#using-vim-packager)
* [Using minpac](#using-minpac)
* [Using vim-plug](#using-vim-plug)
* [Cloning the repo in a pack-start directory](#cloning-the-repo-in-a-pack-start-directory)
* [Documentation](#documentation)
* [Vim help](#vim-help)
* [Wiki](#wiki)
* [In wheel menu](#in-wheel-menu)
* [Configuration](#configuration)
* [Wiki](#wiki-1)
* [Example](#example)
* [Meta-command](#meta-command)
* [Bindings](#bindings)
* [Frequently used functions](#frequently-used-functions)
* [Examples](#examples)
* [Display matching files in splits](#display-matching-files-in-splits)
* [More](#more)
* [Warning](#warning)

# Introduction
## What is it ?

Wheel is a :

- file group manager
- session manager (tabs & windows)
- navigation plugin
- refactoring tool

for Vim and Neovim.

Our favorite editor has already plenty of nice navigation functions. Wheel
enhances their interface by using :

- intuitive completion with multi-pattern support for prompting functions
- dedicated buffers, in which you can filter and select elements, besides using
the full power of your editor
- a meta-command with subcommands, actions and completion
- edit modes, that allow you to reflect your changes in a dedicated buffer to
the original file(s)

With these tools, any line in any file is only a few keys away.

All is written in lightweight, classical Vimscript. No dependency
required.

## What does it look like ?

### History and meta-command

![History & :Wheel command completion](https://github.com/chimay/wheel-multimedia/blob/main/screenshot/history-meta-command.jpg)

### Frecency, dedicated buffers and layers

![Frecency, dedicated buffers and layers](https://github.com/chimay/wheel-multimedia/blob/main/screenshot/mandalas-and-leaves.jpg)

### More screenshots & screencasts

See the [wheel-multimedia repository](https://github.com/chimay/wheel-multimedia).

## File groups & categories

Wheel let you organize your files by creating as many file groups as
you need, add the files you want to it and quickly navigate between :

- files of the same group
- file groups

Note that :

- a location contains a name, a filename, as well as a line & column number
- a file group, in fact a location group, is called a circle
- a set of file groups, or a category, is called a torus (a circle of circles)
- the list of toruses is called the wheel

Currently, there are more than a thousand files in my groups, and it runs like a breeze.

### Why do you need three levels of grouping ?

At first glance, managing groups with circles in a torus seems to be
sufficient. But with time, the torus grows big, and a third level helps
you to organize your files by groups and categories:

- the wheel contains all the toruses
- each torus contains a category of files, e.g.:
+ configuration, development, publication
- each circle contains a project, e.g.:
+ kitty or vifm circles in configuration torus
+ shell or vimscript in development torus
+ tea or art in publication torus

You can also organize a torus in subprojects. For instance, in the wheel
torus, I have the following groups :

- plugin/ dir files
- autoload/ dir files
- doc files
- wiki files
- test files

### A wheel that follows you

Wheel is designed to follow your workflow : you only add the files
you want, where you want. For instance, if you have a `organize` group
with agenda & todo files, you can quickly alternate them, or display
them in two windows. Then, if you suddenly got an idea to tune vim,
you switch to the `vim` group with your favorites configuration files in
it. Same process, to cycle, alternate or display the files. Over time,
your groups will grow and adapt to your style.

## Features

The group manager is the core, but it goes far beyond that : you need a
quick navigation framework to travel in the wheel, and once it is there,
it’s easy to add new functionalities.

- add
+ files from anywhere in the filesystem
+ a file in more than one group
+ file:line-1 and file:line-2 in the same group
- may be saved in wheel file (recommended)
- on demand loading of files
+ no slowdown of (neo)vim start
- easy navigation
+ switch to matching tab & window if available
+ next / previous location, circle or torus
+ single or multi-pattern completion in prompting functions
+ choose file, group or category in dedicated buffer
- filter candidates
- selection tools
- preview
- folds matching wheel tree structure
- context menus
+ auto `:lcd` to project root of current file
+ history of wheel files
- anywhere
- in same group
- in same category
+ signs displayed at wheel locations
- search files
+ using locate
+ using find
+ MRU files not found in wheel
+ opened buffers
+ visible buffers in tabs & windows
- search inside files
+ grep on group files
- navigate
- edit mode : edit and propagate changes by writing the dedicated buffer
+ outline
- folds headers in group files (based on fold markers)
- markdown headers
- org mode headers
+ tags
+ markers
+ jumps & changes lists
- narrow
+ current file
+ all circle file with a pattern
- yank ring using TextYankPost event
+ paste before or after, linewise or characterwise
+ switch register ring
- reorganizing
+ wheel elements
+ tabs & windows
- undo list
+ diff between last & chosen state
- command output in buffer
+ :ex or !shell command
+ async shell command
+ result can be filtered, as usual
- dedicated buffers ring to save your searches
+ layer ring in each dedicated buffer
- batch operations
- autogroup files by extension or directory
- save tabs & windows in minimal session file
- display files
+ split levels : torus, circle, location
+ split
- vertical, golden vertical
- horizontal, golden horizontal
- main left, golden left
- main top, golden top
- grid
+ mix of above
- circles on tabs, locations on split
- toruses on tabs, circles on split

## History

This project is inspired by :

- [torus](https://github.com/chimay/torus), a file group plugin for Emacs,
itself inspired by [MTorus](https://www.emacswiki.org/emacs/MTorus)

- [ctrlspace](https://github.com/vim-ctrlspace/vim-ctrlspace), a workspace
plugin for Vim

- [unite](https://github.com/Shougo/unite.vim), a search plugin for arbitrary sources

- [quickfix-reflector](https://github.com/stefandtw/quickfix-reflector.vim),
for the grep edit mode

- [NrrwRgn](https://github.com/chrisbra/NrrwRgn), for the narrow dedicated buffers

- [YankRing](https://github.com/vim-scripts/YankRing.vim), whose name is
self-explanatory

## Prerequisites

### Software

- vim >= 8.2
- neovim >= 0.6

Basically, it assumes the existence of `:map-cmd` and `#{...}` syntax
for dictionaries.

If your distribution uses an older version, you can resort to appimages :

- [vim appimage](https://github.com/vim/vim-appimage)
- [neovim appimage](https://appimage.github.io/neovim/)

These are fast evolving pieces of software, it's worth upgrading anyway.

### Operating system

Some outer rim functions assume a Unix-like OS, like Linux or BSD :

- async functions
- external commands, like locate
- mirror the wheel structure in a filesystem tree

Most of the plugin should work out of the box on other OSes, however. If
you encounter some problem, please let me know.

# Installation
## Using vim-packager

Simply add this line after `packager#init()` to your initialisation file :

~~~vim
call packager#add('chimay/wheel', { 'type' : 'start' })
~~~

and run `:PackagerInstall` (see the
[vim-packager readme](https://github.com/kristijanhusak/vim-packager)).

## Using minpac

Simply add this line after `minpac#init()` to your initialisation file :

~~~vim
call minpac#add('chimay/wheel', { 'type' : 'start' })
~~~

and run `:PackUpdate` (see the
[minpac readme](https://github.com/k-takata/minpac)).

## Using vim-plug

The syntax should be similar with other git oriented plugin managers :

~~~vim
Plug 'chimay/wheel'
~~~

and run `:PlugInstall` to install.

## Cloning the repo in a pack-start directory

You can clone the repository somewhere in your `runtime-search-path`. You
can get a minimal version by asking a shallow clone (depth 1) and
filtering out the screenshots blobs :

```vim
mkdir -p ~/.local/share/nvim/site/pack/foo/start
cd ~/.local/share/nvim/site/pack/foo/start
git clone --depth 1 --filter=blob:none https://github.com/chimay/wheel
```

If you install or update with git, don't forget to run :

```vim
:helptags doc
```

to be able to use the inline help.

# Documentation
## Vim help

[Your guide](https://github.com/chimay/wheel/blob/master/doc/wheel.txt)
on the wheel tracks :

~~~vim
:help wheel.txt
~~~

## Wiki

A [wheel wiki](https://github.com/chimay/wheel/wiki) is also available.

It is recommended to read at least the
[step-by-step](https://github.com/chimay/wheel/wiki/step-by-step)
and [workflow](https://github.com/chimay/wheel/wiki/workflow)
pages, either in the wiki or in the `wheel.txt` file.

## In wheel menu

In the help submenu of the main menu (default map : ``), you have
access to :

- the inline help (wheel.txt)
- the list of current wheel mappings
- the list of available plug mappings
- the list of :Wheel subcommands and actions
- the list of autocommands of your wheel group
- a dedicated buffer basic help
- local buffer maps

# Configuration
## Wiki

For a thorough list of options, see the
[configuration](https://github.com/chimay/wheel/wiki/configuration)
and
[autocommands](https://github.com/chimay/wheel/wiki/autocommands)
pages in the wiki.

## Example

Here is an example of configuration :

~~~vim
if ! exists("g:wheel_loaded")
" ---- DONT FORGET TO INITIALIZE DICTS BEFORE USING THEM
let g:wheel_config = {}
let g:wheel_config.project = {}
let g:wheel_config.storage = {}
let g:wheel_config.storage.wheel = {}
let g:wheel_config.storage.session = {}
let g:wheel_config.maxim = {}
let g:wheel_config.completion = {}
let g:wheel_config.frecency = {}
let g:wheel_config.display = {}
let g:wheel_config.display.sign = {}

" ---- The bigger it is, the more mappings available
let g:wheel_config.mappings = 10
" ---- Prefix for mappings
let g:wheel_config.prefix = ''
" ---- Locate database ; default one if left empty
let g:wheel_config.locate_db = '~/index/locate/home.db'
" ---- Grep command : :grep or :vimpgrep
let g:wheel_config.grep = 'grep'

" Marker of project root
"let g:wheel_config.project.markers = '.git'
"let g:wheel_config.project.markers = '.project-root'
" List of markers
" The project dir is found as soon as one marker is found in it
let g:wheel_config.project.markers = ['.hg' , '.git', '.project-root']
" Auto cd to project root if > 0
let g:wheel_config.project.auto_chdir = 1

" The folder where toruses and circles will be stored and read
let g:wheel_config.storage.wheel.folder = '~/.local/share/wheel'
" Name of the default wheel file
let g:wheel_config.storage.wheel.name = 'wheel.vim'
" Auto read wheel file on startup if > 0
let g:wheel_config.storage.wheel.autoread = 1
" Auto write wheel file on exit if > 0
let g:wheel_config.storage.wheel.autowrite = 1
" The folder where sessions will be stored and read
let g:wheel_config.storage.session.folder = '~/.local/share/wheel/session'
" Name of the default session file
let g:wheel_config.storage.session.name = 'session.vim'
" Auto read default session file on startup if > 0
let g:wheel_config.storage.session.autoread = 1
" Auto write default session file on exit if > 0
let g:wheel_config.storage.session.autowrite = 1
" Number of backups for wheel & session files
let g:wheel_config.storage.backups = 5

" ---- Maximum number of elements in history
let g:wheel_config.maxim.history = 400
" ---- Maximum number of elements in input history
let g:wheel_config.maxim.input = 200

" ---- Maximum number of elements in mru
let g:wheel_config.maxim.mru = 300

" ---- Maximum number of elements in yank ring
let g:wheel_config.maxim.default_yanks = 700
let g:wheel_config.maxim.other_yanks = 100
" ---- Maximum lines of yank to add in yank ring
let g:wheel_config.maxim.yank_lines = 30
" ---- Maximum size of yank to add in yank ring
let g:wheel_config.maxim.yank_size = 3000

" ---- Maximum size of layer ring
let g:wheel_config.maxim.layers = 10

" ---- Maximum number of tabs in layouts
let g:wheel_config.maxim.tabs = 12
" ---- Maximum number of horizontal splits
let g:wheel_config.maxim.horizontal = 3
" ---- Maximum number of vertical splits
let g:wheel_config.maxim.vertical = 4

" ---- Completion
let g:wheel_config.completion.vocalize = 1
let g:wheel_config.completion.wordize = 1
let g:wheel_config.completion.fuzzy = 0
let g:wheel_config.completion.scores = 1

" ---- Frecency
let g:wheel_config.frecency.reward = 120
let g:wheel_config.frecency.penalty = 1

" ---- Mandala & leaf status in statusline ?
let g:wheel_config.display.statusline = 1
" ---- Wheel dedibuf message : one-line or multi-line
let g:wheel_config.display.dedibuf_msg = 'one-line'
" ---- Filter prompt in dedicated buffers
"let g:wheel_config.display.prompt = 'wheel $ '
"let g:wheel_config.display.prompt_writable = 'wheel # '
" ---- Selection marker in dedicated buffers
"let g:wheel_config.display.selection = '-> '
" ---- Signs
let g:wheel_config.display.sign.switch = 1
" ---- Signs at wheel locations
"let g:wheel_config.display.sign.settings = { 'text' : '@' }
" ---- Signs after using Wheel interface to native navigation (buffer, marker, jump, change, tag, ...)
"let g:wheel_config.display.sign.native_settings = { 'text' : '*' }

let g:wheel_config.debug = 0
endif

augroup wheel
" Clear the group
autocmd!
" On vim enter, for autoreading
autocmd VimEnter * call wheel#void#init()
" On vim leave, for autowriting
autocmd VimLeave * call wheel#void#exit()
" Update location line & col before leaving a window
autocmd BufLeave * call wheel#vortex#update()
" For the generalized alternate window command, for all windows in all tabs
autocmd BufLeave * call wheel#caduceus#update_window()
" Executed before jumping to a location
autocmd User WheelBeforeJump call wheel#vortex#update()
" Executed before organizing the wheel
autocmd User WheelBeforeOrganize call wheel#vortex#update()
" Executed before writing the wheel
autocmd User WheelBeforeWrite call wheel#vortex#update()
" Executed after jumping to a location
"autocmd User WheelAfterJump norm zMzx
" For current wheel location to auto follow window changes
autocmd WinEnter * call wheel#projection#follow()
" For current wheel location to follow on editing, buffer loading
"autocmd BufRead * call wheel#projection#follow()
" For current wheel location to follow on entering buffer
"autocmd BufEnter * call wheel#projection#follow()
" Executed after using Wheel interface to a native jump (buffer, marker, jump, change, tag, ...)
"autocmd User WheelAfterNative call wheel#projection#follow()
" Add current non-wheel file to MRU files
autocmd BufRead * call wheel#attic#record()
" To record your yanks in the yank ring
autocmd TextYankPost * call wheel#codex#add()
augroup END
~~~

# Meta-command

The `:Wheel` meta-command gives you access to almost all the plugin
features :

```vim
:Wheel subcommand
```

Completion is available for subcommands. For further details,
see the
[meta-command wiki page](https://github.com/chimay/wheel/wiki/command).

I suggest you map it to a convenient key. Example :

```vim
nnoremap w :Wheel
```

# Bindings

For a thorough discussion on bindings, see
[the bindings page](https://github.com/chimay/wheel/wiki/bindings)
in the wiki.

## Frequently used functions

Below are some bindings that you may find useful. They are included in
the level 10 mappings :

~~~vim
let nmap = 'nmap '
let vmap = 'vmap '
" Menus
exe nmap ' (wheel-menu-main)'
exe nmap ' (wheel-menu-meta)'
" Sync
exe nmap ' (wheel-info)'
exe nmap ' (wheel-sync-up)'
exe nmap ' (wheel-sync-down)'
" ---- navigate in the wheel
" -- next / previous
exe nmap ' (wheel-previous-location)'
exe nmap ' (wheel-next-location)'
exe nmap ' (wheel-previous-circle)'
exe nmap ' (wheel-next-circle)'
exe nmap ' (wheel-previous-torus)'
exe nmap ' (wheel-next-torus)'
" -- switch
exe nmap ' (wheel-prompt-location)'
exe nmap ' (wheel-prompt-circle)'
exe nmap ' (wheel-prompt-torus)'
exe nmap ' (wheel-dedibuf-location)'
exe nmap ' (wheel-dedibuf-circle)'
exe nmap ' (wheel-dedibuf-torus)'
" -- index
exe nmap ' (wheel-prompt-index)'
exe nmap ' (wheel-dedibuf-index)'
exe nmap ' (wheel-dedibuf-index-tree)'
" -- history
exe nmap ' (wheel-history-newer)'
exe nmap ' (wheel-history-older)'
exe nmap ' (wheel-history-newer-in-circle)'
exe nmap ' (wheel-history-older-in-circle)'
exe nmap ' (wheel-history-newer-in-torus)'
exe nmap ' (wheel-history-older-in-torus)'
exe nmap ' (wheel-prompt-history)'
exe nmap ' (wheel-dedibuf-history)'
" -- alternate
exe nmap ' (wheel-alternate-anywhere)'
exe nmap ' (wheel-alternate-same-circle)'
exe nmap ' (wheel-alternate-same-torus-other-circle)'
" ---- navigate using Wheel interface to vim native tools
" -- buffers
exe nmap ' (wheel-prompt-buffer)'
exe nmap ' (wheel-dedibuf-buffer)'
exe nmap ' (wheel-dedibuf-buffer-all)'
" -- tabs & windows : visible buffers
exe nmap ' (wheel-prompt-tabwin)'
exe nmap ' (wheel-dedibuf-tabwin-tree)'
exe nmap ' (wheel-dedibuf-tabwin)'
" -- (neo)vim lists
exe nmap " (wheel-prompt-marker)"
exe nmap " (wheel-prompt-marker)"
exe nmap ' (wheel-prompt-jump)'
exe nmap ' (wheel-prompt-change)'
exe nmap ' (wheel-prompt-change)'
exe nmap ' (wheel-prompt-tag)'
exe nmap " (wheel-dedibuf-markers)"
exe nmap ' (wheel-dedibuf-jumps)'
exe nmap ' (wheel-dedibuf-changes)'
exe nmap ' (wheel-dedibuf-tags)'
" ---- organize the wheel
exe nmap ' (wheel-prompt-add-here)'
exe nmap ' (wheel-prompt-delete-location)'
exe nmap ' (wheel-dedibuf-reorganize)'
" ---- organize other things
exe nmap ' (wheel-dedibuf-reorg-tabwin)'
" ---- refactoring
exe nmap ' (wheel-dedibuf-grep-edit)'
exe nmap ' (wheel-dedibuf-narrow-operator)'
exe vmap ' (wheel-dedibuf-narrow)'
exe nmap ' (wheel-dedibuf-narrow-circle)'
" ---- search
" -- files
exe nmap ' (wheel-prompt-find)'
exe nmap ' (wheel-dedibuf-find)'
exe nmap ' (wheel-dedibuf-async-find)'
exe nmap ' (wheel-prompt-mru)'
exe nmap ' (wheel-dedibuf-mru)'
exe nmap ' (wheel-dedibuf-locate)'
" -- inside files
exe nmap ' (wheel-prompt-occur)'
exe nmap ' (wheel-dedibuf-occur)'
exe nmap ' (wheel-dedibuf-grep)'
exe nmap ' (wheel-prompt-outline)'
exe nmap ' (wheel-dedibuf-outline)'
" ---- yank ring
exe nmap ' (wheel-prompt-yank-plain-linewise-after)'
exe nmap ' (wheel-prompt-yank-plain-charwise-after)'
exe nmap ' (wheel-prompt-yank-plain-linewise-before)'
exe nmap ' (wheel-prompt-yank-plain-charwise-before)'
exe nmap ' (wheel-dedibuf-yank-plain)'
exe nmap ' (wheel-dedibuf-yank-list)'
" ---- undo list
exe nmap ' (wheel-dedibuf-undo-list)'
" ---- ex or shell command output
exe nmap ' (wheel-dedibuf-command)'
exe nmap ' (wheel-dedibuf-async)'
" ---- dedicated buffers
exe nmap ' (wheel-mandala-add)'
exe nmap ' (wheel-mandala-delete)'
exe nmap ' (wheel-mandala-backward)'
exe nmap ' (wheel-mandala-forward)'
exe nmap ' (wheel-mandala-switch)'
" ---- layouts
exe nmap ' (wheel-zoom)'
~~~

# Examples
## Display matching files in splits

- `` to launch the location navigator
- `i` to go to insert mode
- enter the pattern you want
+ e.g. `\.vim$` if all your vim locations end with `.vim`
- `` to validate the pattern
- `*` to select all the visible (filtered) locations
- `v` to open all selected locations in vertical splits

## More

More examples are available in the
[wiki examples page](https://github.com/chimay/wheel/wiki/examples).

# Warning

Despite abundant testing, some bugs might remain, so be careful.