├── README.md ├── images └── cheat-sheet.gif ├── lua ├── cheat-sheet.lua └── split.lua └── plugin └── after └── cheatsh.vim /README.md: -------------------------------------------------------------------------------- 1 | # Nvim Cheat Sheet 2 | 3 | This plugin allows you to use cheat sheet ([cht.sh](https://cht.sh/)) inside the vim. 4 | 5 | - Plugin written 100 % in lua. 6 | ![](https://github.com/Djancyp/cheat-sheet/blob/main/images/cheat-sheet.gif) 7 | 8 | ## Installation 9 | 10 | Packer 11 | 12 | ```bash 13 | use {"Djancyp/cheat-sheet"} 14 | ``` 15 | 16 | ## Config 17 | 18 | Optionally, you can also pass some configuration to the plugin, here's the default value: 19 | 20 | ```lua 21 | require("cheat-sheet").setup({ 22 | auto_fill = { 23 | filetype = true, 24 | current_word = true, 25 | }, 26 | 27 | main_win = { 28 | style = "minimal", 29 | border = "double", 30 | }, 31 | 32 | input_win = { 33 | style = "minimal", 34 | border = "double", 35 | }, 36 | }) 37 | ``` 38 | 39 | - `auto_fill`: 40 | 41 | - `filetype`: automatically add filetype prefix to search query (ex: `lua/`) 42 | - `current_word`: automatically add the current word under your cursor to search query 43 | 44 | - `main_win`: 45 | 46 | - `style`: main window style (see: `:h nvim_open_win()`) 47 | - `border`: main window border (see: `:h nvim_open_win()`) 48 | 49 | - `input_win`: 50 | 51 | - `style`: input window style (see: `:h nvim_open_win()`) 52 | - `border`: input window border (see: `:h nvim_open_win()`) 53 | 54 | ## Usage 55 | 56 | ```bash 57 | :CheatSH 58 | ``` 59 | 60 | This will open an input window and base on your filetype it will highlight the first part of search. When your query ready just hit the enter. 61 | 62 | ### Ex: 63 | 64 | ``` 65 | lua/for 66 | ``` 67 | 68 | ``` 69 | git/pull 70 | ``` 71 | 72 | ``` 73 | js/async 74 | ``` 75 | 76 | For more information please visit the cheat sheet website - ([cht.sh](https://cht.sh/)) 77 | 78 | ## Keys 79 | 80 | ``` 81 | | Key | Action | 82 | | -------------- | ------------------------------- | 83 | | q | exit cheat sheet window | 84 | | | exit input window (input mode) | 85 | | | remove text (input mode) | 86 | | ``(Enter) | activate the search | 87 | ``` 88 | 89 | ## Contributing 90 | 91 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 92 | 93 | Please make sure to update tests as appropriate. 94 | 95 | ## License 96 | 97 | [MIT](https://choosealicense.com/licenses/mit/) 98 | -------------------------------------------------------------------------------- /images/cheat-sheet.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Djancyp/cheat-sheet/772556d803dbcee914902ae775cca68378bcc90a/images/cheat-sheet.gif -------------------------------------------------------------------------------- /lua/cheat-sheet.lua: -------------------------------------------------------------------------------- 1 | local M = {} 2 | local api = vim.api 3 | 4 | require("split") 5 | 6 | local opts = { 7 | auto_fill = { 8 | filetype = true, 9 | current_word = true, 10 | }, 11 | 12 | main_win = { 13 | style = "minimal", 14 | border = "double", 15 | }, 16 | 17 | input_win = { 18 | style = "minimal", 19 | border = "double", 20 | }, 21 | } 22 | 23 | function M.setup(user_conf) 24 | opts = vim.tbl_deep_extend("force", opts, user_conf or {}) 25 | end 26 | 27 | function M.run() 28 | local ui = api.nvim_list_uis()[1] 29 | M.main_win = nil 30 | M.main_buf = nil 31 | M.main_win_width = math.floor(ui.width / 1.2) 32 | M.main_win_height = math.floor(ui.height / 1.2) 33 | M.main_win_style = opts.main_win.style 34 | M.main_win_relavent = "win" 35 | M.main_win_border = opts.main_win.border 36 | M.main_col = ui.width / 2 - M.main_win_width / 2 37 | M.main_row = ui.height / 2 - M.main_win_height / 2 38 | 39 | M.input_win = nil 40 | M.input_buf = nil 41 | M.input_win_width = 60 42 | M.input_win_height = 1 43 | M.input_win_style = opts.input_win.style 44 | M.input_win_relavent = "win" 45 | M.input_win_border = opts.input_win.border 46 | M.input_col = ui.width / 2 - M.input_win_width / 2 47 | M.input_row = ui.height / 2 - M.input_win_height / 2 48 | 49 | M.openInput() 50 | end 51 | 52 | function M.openInput() 53 | local bufContent = "" 54 | 55 | if opts.auto_fill.filetype then 56 | local fileType = vim.api.nvim_buf_get_option(0, "filetype") 57 | if fileType ~= "" then 58 | bufContent = bufContent .. fileType .. "/" 59 | if not opts.auto_fill.current_word then 60 | bufContent = bufContent .. " " 61 | end 62 | end 63 | end 64 | 65 | if opts.auto_fill.current_word then 66 | local cword = vim.fn.expand("") 67 | if cword then 68 | bufContent = bufContent .. cword .. " " 69 | end 70 | end 71 | 72 | M.input_buf = api.nvim_create_buf(false, true) 73 | M.input_win = api.nvim_open_win(M.input_buf, false, { 74 | relative = M.input_win_relavent, 75 | col = M.input_col, 76 | row = M.input_row, 77 | width = M.input_win_width, 78 | height = M.input_win_height, 79 | style = M.input_win_style, 80 | border = M.input_win_border, 81 | }) 82 | api.nvim_win_set_option(M.input_win, "cursorline", true) 83 | api.nvim_set_current_win(M.input_win) 84 | M.setKey(M.input_buf) 85 | -- add filetype to first line 86 | api.nvim_buf_set_option(M.input_buf, "modifiable", true) 87 | api.nvim_buf_set_lines(M.input_buf, 0, 1, false, { bufContent }) 88 | 89 | -- set cursor on the second line 90 | -- and put it in insert mode 91 | local cursor_input = bufContent:len() + 1 92 | api.nvim_win_set_cursor(M.input_win, { 1, cursor_input }) 93 | api.nvim_command("startinsert") 94 | end 95 | 96 | function Resolve_filetype(sh_filetype) 97 | local fileTypes = { 98 | { 99 | fileType = "c", 100 | alies = { "c", "h" }, 101 | }, 102 | { 103 | fileType = "cpp", 104 | alies = { "cpp", "hpp" }, 105 | }, 106 | { 107 | fileType = "javascript", 108 | alies = { "js", "nodejs", "node", "javascript", "ts", "typescript" }, 109 | }, 110 | { 111 | fileType = "python", 112 | alies = { "py", "python" }, 113 | }, 114 | { 115 | fileType = "ruby", 116 | alies = { "rb", "ruby" }, 117 | }, 118 | { 119 | fileType = "rust", 120 | alies = { "rs", "rust" }, 121 | }, 122 | { 123 | fileType = "kotlin", 124 | alies = { "kt", "kotlin" }, 125 | }, 126 | } 127 | for _, fileType in ipairs(fileTypes) do 128 | if sh_filetype == fileType.fileType then 129 | sh_filetype = fileType.fileType 130 | break 131 | else 132 | for _, alies in ipairs(fileType.alies) do 133 | if sh_filetype == alies then 134 | sh_filetype = fileType.fileType 135 | break 136 | end 137 | end 138 | end 139 | end 140 | return sh_filetype 141 | end 142 | 143 | function M.openPreview() 144 | -- get the text from the input buffer 145 | local input_lines = api.nvim_buf_get_lines(M.input_buf, 0, -1, false) 146 | input_lines = input_lines[1] 147 | if input_lines == "" then 148 | return 149 | end 150 | 151 | local search_fileType = input_lines:split("/") 152 | if #search_fileType > 1 then 153 | -- list all file types in array 154 | search_fileType = Resolve_filetype(search_fileType[1]) 155 | else 156 | search_fileType = "text" 157 | end 158 | 159 | api.nvim_win_close(M.input_win, true) 160 | M.input_win = nil 161 | M.input_buf = nil 162 | 163 | local url = "https://cheat.sh/" .. input_lines 164 | local cmdcommand = "curl -s " .. url 165 | local output = vim.api.nvim_call_function("system", { cmdcommand }) 166 | output = output:split("\n") 167 | local win_height = M.main_win_height 168 | if #output < M.main_win_height then 169 | win_height = #output 170 | end 171 | M.main_buf = api.nvim_create_buf(false, true) 172 | M.main_win = api.nvim_open_win(M.main_buf, false, { 173 | relative = M.main_win_relavent, 174 | width = M.main_win_width, 175 | height = win_height, 176 | style = M.main_win_style, 177 | row = M.main_row, 178 | col = M.main_col, 179 | anchor = "NW", 180 | border = M.main_win_border, 181 | }) 182 | api.nvim_set_current_win(M.main_win) 183 | api.nvim_win_set_option(M.main_win, "cursorline", true) 184 | -- set background color for the window 185 | api.nvim_win_set_option(M.main_win, "winhighlight", "Normal:CursorLine") 186 | api.nvim_buf_set_option(M.main_buf, "filetype", search_fileType) 187 | 188 | for _, line in ipairs(output) do 189 | line = line:gsub("[^m]*m", "") 190 | api.nvim_buf_set_lines(M.main_buf, -1, -1, true, { line }) 191 | end 192 | 193 | api.nvim_buf_set_option(M.main_buf, "modifiable", false) 194 | 195 | M.setKey(M.main_buf) 196 | end 197 | 198 | function M.setKey(buf) 199 | if M.input_buf == nil then 200 | api.nvim_buf_set_keymap( 201 | buf, 202 | "n", 203 | "q", 204 | ':lua require"cheat-sheet".close_win()', 205 | { nowait = true, noremap = true, silent = true } 206 | ) 207 | elseif M.main_buf == nil then 208 | api.nvim_buf_set_keymap( 209 | buf, 210 | "n", 211 | "q", 212 | ':lua require"cheat-sheet".close_win()', 213 | { nowait = true, noremap = true, silent = true } 214 | ) 215 | api.nvim_buf_set_keymap( 216 | buf, 217 | "i", 218 | "", 219 | ':lua require"cheat-sheet".close_win()', 220 | { nowait = true, noremap = true, silent = true } 221 | ) 222 | api.nvim_buf_set_keymap( 223 | buf, 224 | "i", 225 | "", 226 | ':lua require"cheat-sheet".openPreview()', 227 | { nowait = true, noremap = true, silent = true } 228 | ) 229 | api.nvim_buf_set_keymap( 230 | buf, 231 | "n", 232 | "", 233 | ':lua require"cheat-sheet".openPreview()', 234 | { nowait = true, noremap = true, silent = true } 235 | ) 236 | api.nvim_buf_set_keymap( 237 | buf, 238 | "i", 239 | "", 240 | ':lua require"cheat-sheet".removeInput()', 241 | { nowait = true, noremap = true, silent = true } 242 | ) 243 | end 244 | end 245 | 246 | function M.removeInput() 247 | -- remove first line text from input buffer 248 | api.nvim_buf_set_option(M.input_buf, "modifiable", true) 249 | api.nvim_buf_set_lines(M.input_buf, 0, 1, false, {}) 250 | api.nvim_command("startinsert") 251 | end 252 | 253 | function M.close_win() 254 | if M.main_win then 255 | api.nvim_win_close(M.main_win, true) 256 | M.main_win = nil 257 | M.main_buf = nil 258 | elseif M.input_win then 259 | api.nvim_win_close(M.input_win, true) 260 | M.input_win = nil 261 | M.input_buf = nil 262 | end 263 | end 264 | 265 | return M 266 | -------------------------------------------------------------------------------- /lua/split.lua: -------------------------------------------------------------------------------- 1 | local function is_match_empty(pat, plain) 2 | return not not string.find('', pat, nil, plain) 3 | end 4 | 5 | --- String split into table 6 | function string:split(sep, plain) 7 | local str = self 8 | local b, res = 0, {} 9 | sep = sep or '%s+' 10 | 11 | assert(type(sep) == 'string') 12 | assert(type(str) == 'string') 13 | 14 | if #sep == 0 then 15 | for i = 1, #str do 16 | res[#res + 1] = string.sub(str, i, i) 17 | end 18 | return res 19 | end 20 | 21 | assert(not is_match_empty(sep, plain), 'delimiter can not match empty string') 22 | 23 | while b <= #str do 24 | local e, e2 = string.find(str, sep, b, plain) 25 | if e then 26 | res[#res + 1] = string.sub(str, b, e-1) 27 | b = e2 + 1 28 | if b > #str then res[#res + 1] = "" end 29 | else 30 | res[#res + 1] = string.sub(str, b) 31 | break 32 | end 33 | end 34 | return res 35 | end 36 | -------------------------------------------------------------------------------- /plugin/after/cheatsh.vim: -------------------------------------------------------------------------------- 1 | command CheatSH execute "lua require'cheat-sheet'.run()" 2 | --------------------------------------------------------------------------------