https://github.com/teraoka-k/sonido.nvim
a high-speed movement technique by language-specific regex
https://github.com/teraoka-k/sonido.nvim
code-navigation neovim neovim-plugin regex-match
Last synced: 4 months ago
JSON representation
a high-speed movement technique by language-specific regex
- Host: GitHub
- URL: https://github.com/teraoka-k/sonido.nvim
- Owner: teraoka-k
- License: mit
- Created: 2024-11-30T18:44:57.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2025-01-07T05:21:19.000Z (6 months ago)
- Last Synced: 2025-01-07T06:23:00.336Z (6 months ago)
- Topics: code-navigation, neovim, neovim-plugin, regex-match
- Language: Lua
- Homepage:
- Size: 46.9 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Sonído
## Abstract
Define regex once, use it anywhere to navigate through code
## Motivation
When writing a program, you always repeat the same workflow1. skim through top-level structures like class
2. go into the class to skim through functions
3. go into the function to skim through control flows like if, else, while, or for
4. go into the control flow to edit
- function calls
- variable assignments and comparisons
- literals like string, index, key
- type annotations
5. go back to 1, 2, or 3So, shortcuts to navigate to 1,2,3, and 4 are handy
If you haven't setup such keymaps by yourself yet, Sonído is here for you to do that
## Showcase
https://github.com/user-attachments/assets/329e47dd-08c5-49b6-8c44-c40bc6647048
**they are just an example. define regex as your liking**
> **Vim's DEFAULT COMMANDS ARE STILL ACCESSIBLE!** (e.g. type `f` to move to functions and type `f` to find a character in the line)
## Install
### lazy.nvim
```.lua
{
"teraoka-k/sonido.nvim",
config = function() require("sonido").setup({
langs = {
'lua','md','rs',
-- read `Add A New Language` section for other languages and define regex
},
keymaps = {
angle_l = { '<', '>' },
assign_l = { '=', '_' },
class = { 'H', 'L' },
curly_l = { 'C', 'c' },
flow = { '+', '-' },
fn = { 'F', 'f' },
paren_l = { '(', ')' },
pri = {'Fp','fp'},
pub = {'FP','fP'},
ret = { '|', '\\' },
square_l = { '[', ']' },
str_l = { '"', "'" },
type = { 'T', 't' },
},
}) end
}
```e.g. `fn = {'F', 'f'}` means type `F` to move to previous function, and `f` to next
#### Definitions
default features' definitions
##### for programming languages
- angle_l : left angle bracket `<`
- angle_r : left angle bracket `>`
- assign: `let foo = 1` `foo = 2` `foo += 1` etc
- class : `class Foo` `Struct Foo` `impl Foo` etc
- curly_l : `{`
- curly_r : `}`
- flow : control flows `if` `else` `while` `for i in array` etc
- fn : functions and closures
- paren_l : `(`
- paren_r : `)`
- pri : private
- pub : public
- ret : `return` (`end` for lua)
- square_l: `[`
- square_r: `]`
- str_l : f for `"foo"` `'foo'`
- str_r : o for `"foo"` `'foo'`
- type : type annotations##### for markdown
- angle_l :
> quote or
- assign : font (**bold** *italic* underscore)
- class : # Header1 or ## Header2
- curly_l : `{`
- flow : top-level list `-` `*` `1.`
- fn : # ## ### ####... all headers
- paren_l : `(`
- square_l: [link](https://) or 
- str_l : `inline-code` or code block## Config
all of the settings below are optional
if you want to add a support for a new language, read **Add A New Language** section too.
### Features
specify features to use
all features are active by default
```.lua
{
config = function() require("sonido").setup({
feats = {
'angle_l',
'angle_r',
'assign',
'class',
'curly_l',
'curly_r',
'flow',
'fn',
'paren_l',
'paren_r',
'pri',
'pub',
'ret',
'square_l',
'square_r',
'str_l',
'str_r',
'type',
-- and any custom features
-- 'custom_feature_1'
},
}) end
}
```### Languages
select file-extensions to activate Sonído
```.lua
{
config = function() require("sonido").setup({
langs = {
'lua', 'md', 'rs',
-- and any user_defined file types
-- 'js',
},
}) end
}
```**To use languages other than 'lua', 'md', 'rs', you must define regex**
See the **Add A New Language** section for detail
### Repeat
all the movement is repeatalbe by default
```
{
config = function() require("sonido").setup({
is_repeatable = true
}) end
}
```### Modes
normal and visual modes are active by default
```.lua
{
config = function() require("sonido").setup({
modes = { 'n', 'v', 'i', 'o' },
}) end
}
```### Escape Prefix
Vim's default keys including `[` `]` cannot be overridden easily, as many keys starting with those keys dynamically turned on/off every time buffers are opened/closed. This plugin allows users to override these keys, and the original commands of these keys are accessible by typing with a prefix (e.g.)`[` `]`.
default is ``
```.lua
{
config = function() require("sonido").setup({
escape_prefix = '',
}) end
}
```
### Jump
a feature like minimal [easy-motion](https://github.com/easymotion/vim-easymotion)instead of displaying labels, immediately move to the closest matched words after typing n chars, then type `,` or `;` to adjust the position
**disabled by default**
```
{
config = function() require("sonido").setup({
jump = {
-- S key to search backwards by 2 chars
'S',
-- s key to search forwards by 2 chars
's',
-- 2 chars. change to any positive integer
2,
},
}) end
}
```### Add A New Language
add regular expressions as follows
all the patterns are `very magic`. any pattern that works as `/\v pattern` should work for Sonído too.
run `:h pattern` and search `very magic` for detail```.lua
{
config = function() require("sonido").setup({-- a file extension
langs = { 'js' },-- add keymaps for user-defined regex
keymaps = {
user_defined_custom_symbol = {
'P', 'p'
},
},
-- define symbols for each language
symbols= {-- a file extension
js = {
angle_l = [[\<]],
assign = [[\S+\s?[+-\*&|<>=]?(&&|||)?\=\s?\S]],-- class = 'class ', -- move to `c`
class = 'class /;/ /;/\S', -- move to `F` for `class Foo`curly_l = [[\{]],
flow = [[(for .* (in|of)|while|if|else) ]],-- fn= "function .{-}|(.{-}) => ", -- move to `f`
fn= "function .{-}|(.{-}) => /;/ /;/\S", -- move to `b` for `function bar(...)`paren_l = [[\(]],
pri = [[private /;/ /;/\S]],
pub = [[public /;/ /;/\S]],
ret = [[return.*$]],
square_l = '\\[',
str_l = [[(['"`]).{-}\1]]user_defined_custom_symbol = 'private ',
}-- a file extension
cpp = {...}}
})
end
}
```as in Vim's default search, use `foo/;/bar` to move to `bar` preceeded by `foo`
#### File Mangement
it's better to put the symbols to separate files as they grow up easily as time goes on
##### ~/.config/nvim/sonido-lang/js.lua
```lua
return {
angle_l = {},
assign_r = {},
...
}
```and import it to init.lua so that it's easy to adjust settings reagardless of number of languages
##### init.lua
```lua
config = function()
local js = require('sonido-lang.js')require("sonido").setup({
langs = { 'js', 'jsx', 'cpp' },
keymaps = {
user_defined_custom_symbol = {
'P', 'p'
},
},
symbols = {
js = js,
jsx = js,
cpp = require("sonido-lang.cpp"),
}
})
end
```