├── .gitignore ├── LICENSE ├── MANUAL.md ├── README.md ├── autoload └── quickui │ ├── command.vim │ ├── confirm.vim │ ├── context.vim │ ├── core.vim │ ├── highlight.vim │ ├── input.vim │ ├── listbox.vim │ ├── menu.vim │ ├── palette.vim │ ├── palette9.vim │ ├── preview.vim │ ├── readline.vim │ ├── style.vim │ ├── tags.vim │ ├── terminal.vim │ ├── textbox.vim │ ├── tools.vim │ ├── utils.vim │ └── window.vim ├── colors └── quickui │ ├── borland.vim │ ├── default.vim │ ├── gruvbox.vim │ ├── papercol_dark.vim │ ├── papercol_light.vim │ ├── solarized.vim │ └── system.vim ├── plugin └── quickui.vim └── test ├── demo_menu.vim ├── example_menu.vim ├── menu_example.vim ├── test_confirm.vim ├── test_listbox.vim ├── test_nvim_context.vim ├── test_nvim_list.vim ├── test_nvim_menu.vim ├── test_nvim_popup.vim ├── test_nvim_textbox.vim ├── test_readline.vim ├── test_readline2.vim ├── test_terminal.vim ├── test_textbox.vim └── test_window.vim /.gitignore: -------------------------------------------------------------------------------- 1 | /doc/tags 2 | /update.cmd 3 | 4 | /autoload/quickui/speedkey.vim 5 | /autoload/quickui/speedlib.vim 6 | 7 | /.vscode/* 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Linwei 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # What Is It ? 2 | 3 | There are many keymaps defined in my `.vimrc`. Getting tired from checking `.vimrc` time to time when I forget some, based on the latest `+popup` feature (vim 8.2), I created this `vim-quickui` plugin to introduce some basic UI components to enrich vim's interactive experience: 4 | 5 | - Well designed and carefully colored Borland/Turbo C++ flavor ui system combined with vim's productivity. 6 | - Can be accessed by keyboard only while mouse is also supported. 7 | - Navigate with the usual Vim keys like `h/j/k/l`, confirm with `ENTER/SPACE` and cancel with `ESC/Ctrl+[`. 8 | - `Tip` for each entry can display in the cmdline when you are moving the cursor around. 9 | - Available widgets: [menu](#menu), [listbox](#listbox), [inputbox](#inputbox), [textbox](#textbox).. (coming soon) 10 | - Fully customizable, including color scheme and borders. 11 | - Corresponding experience in both `Vim` and `NeoVim`. 12 | - Pure vim-script, `+python` is not required. 13 | - No longer have to be afraid to forget keymaps anymore. 14 | 15 | Just see this GIF demonstration below: 16 | 17 | ![](https://skywind3000.github.io/images/p/quickui/screenshot.gif) 18 | 19 | Trying to share my configuration to my friends, I found that they did't have patience to remember all the keymaps in my vimrc, but text ui is quite acceptable for them. 20 | 21 | # Content 22 | 23 | 24 | 25 | - [What Is It ?](#what-is-it-) 26 | - [Content](#content) 27 | - [Relative Projects](#relative-projects) 28 | - [Requirements](#requirements) 29 | - [Installation](#installation) 30 | - [Gallery Screenshot](#gallery-screenshot) 31 | - [Menu](#menu) 32 | - [Listbox](#listbox) 33 | - [Inputbox](#inputbox) 34 | - [Context menu](#context-menu) 35 | - [Textbox](#textbox) 36 | - [Preview window](#preview-window) 37 | - [Terminal](#terminal) 38 | - [Confirm dialog](#confirm-dialog) 39 | - [User Manual](#user-manual) 40 | - [Who Am I ?](#who-am-i-) 41 | - [Credit](#credit) 42 | 43 | 44 | 45 | ## Relative Projects 46 | 47 | Plugins powered by QuickUI: 48 | 49 | - [vim-navigator](https://github.com/skywind3000/vim-navigator): Navigate your commands easily. 50 | 51 | ## Requirements 52 | 53 | - Vim: 8.2 or later. 54 | - NeoVim: 0.4.0 or later. 55 | 56 | ## Installation 57 | 58 | Plug 'skywind3000/vim-quickui' 59 | 60 | For more information, please see the [User Manual](MANUAL.md). 61 | 62 | ## Gallery Screenshot 63 | 64 | ### Menu 65 | 66 | Display a dropdown menubar at top of the screen, use `hjkl` or mouse to navigate: 67 | 68 | ![](https://skywind3000.github.io/images/p/quickui/mainmenu.png) 69 | 70 | Customizable border style: 71 | 72 | ![](https://skywind3000.github.io/images/p/quickui/border2.png) 73 | 74 | Menu color schemes: 75 | 76 | ![](https://skywind3000.github.io/images/p/quickui/colors.png) 77 | 78 | See: [Menu help](MANUAL.md#menu). 79 | 80 | ### Listbox 81 | 82 | When you have hundres of items to deal with, menu is not enough to hold them. Then you will need a listbox. 83 | 84 | ![](https://skywind3000.github.io/images/p/quickui/listbox.png) 85 | 86 | It has scroll bar, content can be scrolled by keyboard or mouse wheel. You can search items with `/` or `?` command. 87 | 88 | It can be used to select buffers or functions in current file: 89 | 90 | ![](https://skywind3000.github.io/images/p/quickui/list-function.png) 91 | 92 | The cursor will stay in the current function initially. Navigate and press enter to jump to the selected function. 93 | 94 | See: [Listbox help](MANUAL.md#listbox). 95 | 96 | ### Inputbox 97 | 98 | Prompt user to input a string in a TUI box: 99 | 100 | ![](https://skywind3000.github.io/images/p/quickui/input1.png) 101 | 102 | Could be used as a drop-in replacement of `input()` function. 103 | 104 | See: [Input box help](MANUAL.md#inputbox). 105 | 106 | ### Context menu 107 | 108 | Context menu imitates Windows context menu (triggered by your mouse right button), which will display around the cursor: 109 | 110 | ![](https://skywind3000.github.io/images/p/quickui/context.png) 111 | 112 | It is usually used to present some commands that will do something with source code in the current line. 113 | 114 | The border can be changed too: 115 | 116 | ![](https://skywind3000.github.io/images/p/quickui/context2.png) 117 | 118 | Because some terminals or fonts cannot display unicode borders correctly, so QuickUI choose ascii border characters by default. But you can change it as you like. 119 | 120 | See: [Context menu help](MANUAL.md#context-menu). 121 | 122 | ### Textbox 123 | 124 | Textbox is used to display arbitrary text in a popup window. 125 | 126 | ![](https://skywind3000.github.io/images/p/quickui/textbox.png) 127 | 128 | Display vim help with syntax highlighting in the `textbox`: 129 | 130 | ![](https://skywind3000.github.io/images/p/quickui/display-help.png) 131 | 132 | With `textbox`, you can read the help text at anytime in a popup, without creating a new split window. 133 | 134 | Display vim messages: 135 | 136 | ![](https://skywind3000.github.io/images/p/quickui/messages.png) 137 | 138 | Navigating the messages with `HJKL` or `PageUp/PageDown` is much more convenient than using `:messages`. 139 | 140 | See: [Text box help](MANUAL.md#textbox). 141 | 142 | ### Preview window 143 | 144 | Preview window is used to replace traditional `pedit` command and can be used to display certain file in a small popup window around your cursor: 145 | 146 | ![](https://skywind3000.github.io/images/p/quickui/preview.png) 147 | 148 | Sometimes I just want a glimpse to the definition of the current word under cursor without actually open that file, the `preview` window is much helpful for this. 149 | 150 | Use it to preview quickfix result: 151 | 152 | ![](https://skywind3000.github.io/images/p/quickui/quickfix.png) 153 | 154 | If you have many items in the quickfix window, instead of open them one by one, you are able to press `p` in the quickfix window and preview them in the popup. 155 | 156 | See: [Preview window help](MANUAL.md#preview-window). 157 | 158 | ### Terminal 159 | 160 | The `terminal` widget can allow you open a terminal in the popup window: 161 | 162 | ![](https://skywind3000.github.io/images/p/quickui/terminal.png) 163 | 164 | This feature require vim `8.2.200` (nvim `0.4.0`) or later, it enables you to run various tui programs in a dialog window. 165 | 166 | See: [Terminal help](MANUAL.md#terminal). 167 | 168 | ### Confirm dialog 169 | 170 | This widget offers user a dialog, from which a choice can be made: 171 | 172 | ![](https://skywind3000.github.io/images/p/quickui/confirm1.png) 173 | 174 | It returns the number of the choice. For the first choice, this is 1. 175 | 176 | See: [Confirm dialog help](MANUAL.md#confirm-dialog). 177 | 178 | 179 | ## User Manual 180 | 181 | To get started, please visit: 182 | 183 | - [User Manual](MANUAL.md) 184 | 185 | For more examples, see [my config](test/menu_example.vim). 186 | 187 | 188 | ## Who Am I ? 189 | 190 | My name is Lin Wei, and I am a strong advocate of open source and a passionate vim user. I embarked on my programming journey in the early 1990s. During that time, Borland’s Turbo Pascal/C++ served as the prevailing IDE, and I fondly reminisce about those days. After returning home from school, I would eagerly power on my computer, launch Turbo C++ 3.1, and delve into the world of creating games in MS-DOS. 191 | 192 | I even imitated Turbo C++ and made my own editor when I moved to Watcom C++: 193 | 194 | ![](https://skywind3000.github.io/images/p/quickui/editor.png) 195 | 196 | Because I didn't own a proper editor/IDE for Watcom C++ at that time. 197 | 198 | During my transition to Windows, I encountered a multitude of GUI editors, ranging from UltraEdit and EditPlus to Notepad++ and even gedit and geany. However, none of them managed to fulfill my requirements completely. Each day, I found myself grappling with the constant need to learn new IDEs, editors, or frameworks, which left me exhausted and disconnected from the true joy of programming. It was not until I discovered vim that everything changed. Instantly, I became enamored with its capabilities and found my passion for programming reignited. 199 | 200 | With the continuous evolution of Vim, thanks to Bram’s unwavering efforts, the release of version 8.2 has brought forth exciting possibilities. It dawned on me that perhaps I can now incorporate some of the cool features from 25 years ago into Vim. Just like my experiences as a middle school student, learning to create PC games during the golden era of the 1990s, I can now infuse my everyday work with a nostalgic Borland/Turbo C++ flavor, courtesy of Vim. 201 | 202 | The time has come for me to transform these ideas into reality, and it all begins with this plugin. 203 | 204 | ## Credit 205 | 206 | like vim-quickui? Follow the repository on [GitHub](https://github.com/skywind3000/vim-quickui) and vote for it on [vim.org](https://www.vim.org/scripts/script.php?script_id=5845). And if you're feeling especially charitable, follow skywind3000 on [Twitter](https://twitter.com/skywind3000) and [GitHub](https://github.com/skywind3000). 207 | 208 | -------------------------------------------------------------------------------- /autoload/quickui/command.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " main.vim - 4 | " 5 | " Created by skywind on 2022/08/24 6 | " Last Modified: 2022/08/24 20:24:47 7 | " 8 | "====================================================================== 9 | 10 | " vim: set ts=4 sw=4 tw=78 noet : 11 | 12 | 13 | "---------------------------------------------------------------------- 14 | " extension map 15 | "---------------------------------------------------------------------- 16 | let g:quickui = get(g:, 'quickui', {}) 17 | let s:quickui = {} 18 | 19 | 20 | "---------------------------------------------------------------------- 21 | " internal 22 | "---------------------------------------------------------------------- 23 | let s:private = {} 24 | let s:private.quickui = {} 25 | 26 | 27 | "---------------------------------------------------------------------- 28 | " initialize 29 | "---------------------------------------------------------------------- 30 | function! s:init() 31 | let quickui = {} 32 | for key in keys(s:quickui) 33 | let quickui[key] = s:quickui[key] 34 | endfor 35 | for key in keys(g:quickui) 36 | let quickui[key] = g:quickui[key] 37 | endfor 38 | let names = keys(quickui) 39 | call sort(names) 40 | let s:private.quickui = quickui 41 | let s:private.names = names 42 | endfunc 43 | 44 | 45 | "---------------------------------------------------------------------- 46 | " help 47 | "---------------------------------------------------------------------- 48 | function! s:help(opts, argv) 49 | endfunc 50 | 51 | 52 | "---------------------------------------------------------------------- 53 | " list extension 54 | "---------------------------------------------------------------------- 55 | function! s:list(opts, argv) 56 | let rows = [] 57 | let highmap = {} 58 | let index = 1 59 | let rows += [['Extension', 'Help']] 60 | let highmap['0,0'] = 'Title' 61 | let highmap['0,1'] = 'Title' 62 | for name in s:private.names 63 | let help = get(s:private.quickui[name], 'help', '') 64 | let rows += [[name, help]] 65 | let highmap[index . ',0'] = 'Keyword' 66 | let highmap[index . ',1'] = 'Statement' 67 | let index += 1 68 | endfor 69 | call quickui#utils#print_table(rows, highmap) 70 | endfunc 71 | 72 | 73 | "---------------------------------------------------------------------- 74 | " main cmd 75 | "---------------------------------------------------------------------- 76 | function! quickui#command#run(bang, cmdline) abort 77 | let [cmdline, op1] = quickui#core#extract_opts(a:cmdline) 78 | let cmdline = quickui#core#string_strip(cmdline) 79 | let name = '' 80 | if cmdline =~# '^\w\+' 81 | let name = matchstr(cmdline, '^\w\+') 82 | let cmdline = substitute(cmdline, '^\w\+\s*', '', '') 83 | endif 84 | let name = quickui#core#string_strip(name) 85 | let [cmdline, op2] = quickui#core#extract_opts(cmdline) 86 | let op2.cmdline = quickui#core#string_strip(cmdline) 87 | let opts = deepcopy(op1) 88 | for k in keys(op2) 89 | let opts[k] = op2[k] 90 | endfor 91 | let argv = quickui#core#split_argv(cmdline) 92 | call s:init() 93 | if name == '' 94 | if has_key(op1, 'h') 95 | call s:help(opts, argv) 96 | elseif has_key(op1, 'l') 97 | call s:list(opts, argv) 98 | endif 99 | return 0 100 | endif 101 | if has_key(s:private.quickui, name) == 0 102 | call quickui#utils#errmsg('invalid extension name: ' . name) 103 | return -1 104 | endif 105 | let obj = s:private.quickui[name] 106 | if has_key(obj, 'run') == 0 107 | call quickui#utils#errmsg('not find "run" funcref in extension: ' . name) 108 | return -2 109 | endif 110 | let hr = call(obj.run, [opts, argv]) 111 | return hr 112 | endfunc 113 | 114 | 115 | 116 | "---------------------------------------------------------------------- 117 | " command line completion 118 | "---------------------------------------------------------------------- 119 | function! quickui#command#complete(ArgLead, CmdLine, CursorPos) 120 | let candidate = [] 121 | call s:init() 122 | if a:ArgLead =~ '^-' 123 | let flags = ['-h', '-l'] 124 | for flag in flags 125 | if stridx(flag, a:ArgLead) == 0 126 | let candidate += [flag] 127 | endif 128 | endfor 129 | return candidate 130 | endif 131 | for name in s:private.names 132 | if stridx(name, a:ArgLead) == 0 133 | let candidate += [name] 134 | endif 135 | endfor 136 | return candidate 137 | endfunc 138 | 139 | 140 | "---------------------------------------------------------------------- 141 | " sub: main menu 142 | "---------------------------------------------------------------------- 143 | function! s:sub_menu(opts, argv) abort 144 | let argv = a:argv 145 | if len(argv) == 0 146 | call quickui#menu#open() 147 | else 148 | call quickui#menu#open(argv[0]) 149 | endif 150 | endfunc 151 | 152 | let s:quickui.menu = { 153 | \ 'run': function('s:sub_menu'), 154 | \ 'help': 'open main menu', 155 | \ } 156 | 157 | 158 | "---------------------------------------------------------------------- 159 | " sub: context menu 160 | "---------------------------------------------------------------------- 161 | function! s:sub_context(opts, argv) abort 162 | let context = [] 163 | if exists('g:quickui_context') 164 | for item in g:quickui_context 165 | let context += [item] 166 | endfor 167 | endif 168 | if exists('b:quickui_context') 169 | if !empty(context) 170 | let context += ['--'] 171 | endif 172 | for item in b:quickui_context 173 | let context += [item] 174 | endfor 175 | endif 176 | if exists('g:quickui_context_foot') 177 | if !empty(context) 178 | let context += ['--'] 179 | endif 180 | for item in g:quickui_context_foot 181 | let context += [item] 182 | endfor 183 | endif 184 | let opts = {} 185 | if !empty(context) 186 | call quickui#tools#clever_context('_', context, opts) 187 | endif 188 | endfunc 189 | 190 | let s:quickui.context = { 191 | \ 'run': function('s:sub_context'), 192 | \ 'help': 'open context menu', 193 | \ } 194 | 195 | 196 | "---------------------------------------------------------------------- 197 | " sub: terminal 198 | "---------------------------------------------------------------------- 199 | function! s:sub_terminal(opts, argv) abort 200 | let cmd = a:opts.cmdline 201 | " echom printf("cmd is '%s', type: %d", cmd, type(cmd)) 202 | " echom a:opts 203 | return quickui#terminal#open(cmd, a:opts) 204 | endfunc 205 | 206 | let s:quickui.terminal = { 207 | \ 'run': function('s:sub_terminal'), 208 | \ 'help': 'open terminal window', 209 | \ } 210 | 211 | 212 | -------------------------------------------------------------------------------- /autoload/quickui/confirm.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " confirm.vim - 4 | " 5 | " Created by skywind on 2021/12/11 6 | " Last Modified: 2021/12/13 22:07 7 | " 8 | "====================================================================== 9 | 10 | " vim: set ts=4 sw=4 tw=78 noet : 11 | 12 | 13 | "---------------------------------------------------------------------- 14 | " build buttons 15 | "---------------------------------------------------------------------- 16 | function! s:button_prepare(choices) 17 | let choices = quickui#utils#text_list_normalize(a:choices) 18 | let items = [] 19 | let index = 0 20 | let max_size = 4 21 | for choice in choices 22 | let item = quickui#utils#item_parse(choice) 23 | let item.index = index 24 | let items += [item] 25 | let width = item.text_width 26 | let max_size = (max_size < width)? width : max_size 27 | let index += 1 28 | endfor 29 | for item in items 30 | let width = item.text_width 31 | let pad1 = (max_size - width) / 2 32 | let pad2 = max_size - width - pad1 33 | " let pad1 += 1 34 | " let pad2 += 1 35 | let item.text = repeat(' ', pad1) . item.text . repeat(' ', pad2) 36 | if item.key_pos >= 0 37 | let item.key_pos += pad1 38 | endif 39 | let item.text_width = strwidth(item.text) 40 | endfor 41 | return items 42 | endfunc 43 | 44 | 45 | "---------------------------------------------------------------------- 46 | " synthesis button line 47 | "---------------------------------------------------------------------- 48 | function! s:button_finalize(items, style) 49 | let items = a:items 50 | let final = '' 51 | let start = 0 52 | let index = len(a:items) - 1 53 | for item in a:items 54 | if 0 55 | let text = ' ' . item.text . ' ' 56 | else 57 | let text = '<' . item.text . '>' 58 | endif 59 | let item.offset = -1 60 | let need = 0 61 | if 0 62 | let need = 1 63 | let text = '[' . text . ']' 64 | endif 65 | if item.key_pos >= 0 66 | let item.offset = start + 1 + item.key_pos + need 67 | endif 68 | let item.start = start 69 | let item.endup = start + item.text_width + 2 + need * 2 70 | let start += item.text_width + 2 + need * 2 71 | let final .= text 72 | if index > 0 73 | let final .= ' ' 74 | let start += 2 75 | endif 76 | let index -= 1 77 | endfor 78 | return final 79 | endfunc 80 | 81 | 82 | "---------------------------------------------------------------------- 83 | " create highlight 84 | "---------------------------------------------------------------------- 85 | function! s:hl_prepare(hwnd) 86 | let hwnd = a:hwnd 87 | let c1 = get(g:, 'quickui_button_color_on', 'QuickSel') 88 | let c2 = get(g:, 'quickui_button_color_off', 'QuickBG') 89 | let ck = get(g:, 'quickui_button_color_key', 'QuickKey') 90 | let hwnd.color_on = c1 91 | let hwnd.color_off = c2 92 | let hwnd.color_on2 = 'QuickButtonOn2' 93 | let hwnd.color_off2 = 'QuickButtonOff2' 94 | call quickui#highlight#clear('QuickBUttonOn2') 95 | call quickui#highlight#clear('QuickBUttonOff2') 96 | if 0 97 | call quickui#highlight#overlay('QuickButtonOn2', c1, ck) 98 | call quickui#highlight#overlay('QuickButtonOff2', c2, ck) 99 | else 100 | call quickui#highlight#make_underline('QuickButtonOn2', c1) 101 | call quickui#highlight#make_underline('QuickButtonOff2', c2) 102 | endif 103 | endfunc 104 | 105 | 106 | "---------------------------------------------------------------------- 107 | " calculate requirements 108 | "---------------------------------------------------------------------- 109 | function! s:init(text, choices, index, title) 110 | let hwnd = {} 111 | let hwnd.text = quickui#utils#text_list_normalize(a:text) 112 | let hwnd.items = s:button_prepare(a:choices) 113 | let hwnd.final = s:button_finalize(hwnd.items, 0) 114 | let hwnd.index = a:index 115 | let button = '' 116 | let text_size = 40 117 | for text in hwnd.text 118 | let ts = strdisplaywidth(text) 119 | let text_size = (text_size < ts)? ts : text_size 120 | endfor 121 | let limit = &columns * 80 / 100 122 | let limit = get(g:, 'quickui_confirm_max_width', limit) 123 | let text_size = (text_size < limit)? text_size : limit 124 | let hwnd.btn_size = strdisplaywidth(hwnd.final) 125 | let hwnd.text_size = text_size 126 | let hwnd.w = (hwnd.btn_size > text_size)? hwnd.btn_size : text_size 127 | let hwnd.h = len(hwnd.text) + 3 128 | let hwnd.tw = hwnd.w + 4 129 | let hwnd.th = hwnd.h + 4 130 | let border = g:quickui#style#border 131 | let opts = {} 132 | let opts.w = hwnd.w 133 | let opts.h = hwnd.h 134 | let opts.border = get(g:, 'quickui_confirm_border', border) 135 | let opts.center = 1 136 | let opts.title = (a:title == '')? '' : (' ' . a:title . ' ') 137 | let opts.padding = [1, 1, 1, 1] 138 | let opts.button = 1 139 | let opts.wrap = 1 140 | let hwnd.opts = opts 141 | let content = deepcopy(hwnd.text) 142 | let content += [' ', ' '] 143 | let hwnd.padding = hwnd.w - hwnd.btn_size 144 | let content += [repeat(' ', hwnd.padding) . hwnd.final] 145 | let hwnd.content = content 146 | let hwnd.win = quickui#window#new() 147 | let hwnd.keymap = quickui#utils#keymap() 148 | let index = 1 149 | for item in hwnd.items 150 | if item.key_pos >= 0 151 | let ch = tolower(item.key_char) 152 | let hwnd.keymap[ch] = 'ACCEPT:' . index 153 | endif 154 | let index += 1 155 | endfor 156 | let hwnd.keymap['h'] = 'LEFT' 157 | let hwnd.keymap['l'] = 'RIGHT' 158 | call s:hl_prepare(hwnd) 159 | return hwnd 160 | endfunc 161 | 162 | 163 | "---------------------------------------------------------------------- 164 | " 165 | "---------------------------------------------------------------------- 166 | function! s:draw_button(hwnd, index) 167 | let hwnd = a:hwnd 168 | let item = hwnd.items[a:index] 169 | let index = a:index 170 | let win = hwnd.win 171 | let top = hwnd.h - 1 172 | let off = hwnd.padding 173 | let x = item.start 174 | let e = item.endup 175 | if hwnd.index == index 176 | let c1 = hwnd.color_on 177 | let c2 = hwnd.color_on2 178 | " let c1 = 'QuickSel' 179 | else 180 | let c1 = hwnd.color_off 181 | let c2 = hwnd.color_off2 182 | " let c1 = 'QuickBG' 183 | " return 184 | endif 185 | if item.offset < 0 186 | call win.syntax_region(c1, off + x, top, off + e, top) 187 | else 188 | let u = item.offset + off 189 | call win.syntax_region(c1, off + x, top, u, top) 190 | call win.syntax_region(c2, u, top, u + 1, top) 191 | call win.syntax_region(c1, u + 1, top, off + e, top) 192 | endif 193 | endfunc 194 | 195 | 196 | "---------------------------------------------------------------------- 197 | " render 198 | "---------------------------------------------------------------------- 199 | function! s:render(hwnd) 200 | let hwnd = a:hwnd 201 | let win = hwnd.win 202 | let off = hwnd.padding 203 | let top = hwnd.h - 1 204 | let index = 0 205 | call win.syntax_begin(1) 206 | for item in hwnd.items 207 | call s:draw_button(hwnd, index) 208 | let index += 1 209 | endfor 210 | " call win.syntax_region(ck, 12, 0, 13, 0) 211 | call win.syntax_end() 212 | endfunc 213 | 214 | 215 | "---------------------------------------------------------------------- 216 | " main entry 217 | "---------------------------------------------------------------------- 218 | function! quickui#confirm#open(text, ...) 219 | let choices = (a:0 < 1)? " &OK " : (a:1) 220 | let index = (a:0 < 2)? 1 : (a:2) 221 | let title = (a:0 < 3)? 'Confirm' : (a:3) 222 | let choices = (choices == '')? " &OK " : choices 223 | let hwnd = s:init(a:text, choices, index - 1, title) 224 | let win = hwnd.win 225 | let accept = 0 226 | let size = len(hwnd.items) 227 | 228 | if size == 0 229 | return 0 230 | endif 231 | 232 | if has('nvim') 233 | let hwnd.opts.focusable = 1 234 | endif 235 | 236 | call win.open(hwnd.content, hwnd.opts) 237 | 238 | while 1 239 | call s:render(hwnd) 240 | redraw 241 | let ch = quickui#utils#getchar(1) 242 | if ch == "\" || ch == "\" 243 | let accept = 0 244 | break 245 | elseif ch == "\" || ch == "\" 246 | let accept = hwnd.index + 1 247 | break 248 | elseif win.quit != 0 249 | let accept = 0 250 | break 251 | elseif ch == "\" 252 | if has('nvim') == 0 253 | let pos = getmousepos() 254 | let x = pos.column - 1 255 | let y = pos.line - 1 256 | else 257 | let x = v:mouse_col - 1 258 | let y = v:mouse_lnum - 1 259 | endif 260 | if v:mouse_winid == win.winid 261 | if y == hwnd.h - 1 && x >= hwnd.padding 262 | let u = x - hwnd.padding 263 | for item in hwnd.items 264 | if u >= item.start && u < item.endup 265 | let accept = item.index + 1 266 | break 267 | endif 268 | endfor 269 | if accept > 0 270 | break 271 | endif 272 | endif 273 | elseif v:mouse_winid == win.info.border_winid 274 | if y == 0 && x == win.info.tw - 1 275 | let accept = 0 276 | break 277 | endif 278 | endif 279 | else 280 | let key = get(hwnd.keymap, ch, ch) 281 | if key == 'LEFT' 282 | let hwnd.index = (hwnd.index > 0)? (hwnd.index - 1) : 0 283 | elseif key == 'RIGHT' 284 | if hwnd.index < size - 1 285 | let hwnd.index += 1 286 | endif 287 | elseif key == 'HOME' || key == 'UP' || key == 'PAGEUP' 288 | let hwnd.index = 0 289 | elseif key == 'END' || key == 'DOWN' || key == 'PAGEDOWN' 290 | let hwnd.index = size - 1 291 | elseif key =~ '^ACCEPT:' 292 | let key = strpart(key, 7) 293 | let index = str2nr(key) 294 | if index > 0 && index <= size 295 | let accept = index 296 | break 297 | endif 298 | endif 299 | endif 300 | endwhile 301 | 302 | if accept > 0 && win.quit == 0 303 | let hwnd.index = accept - 1 304 | call s:render(hwnd) 305 | redraw 306 | sleep 15m 307 | endif 308 | 309 | call win.close() 310 | 311 | return accept 312 | endfunc 313 | 314 | 315 | 316 | -------------------------------------------------------------------------------- /autoload/quickui/highlight.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " highlight.vim - 4 | " 5 | " Created by skywind on 2021/12/12 6 | " Last Modified: 2021/12/13 18:32 7 | " 8 | "====================================================================== 9 | 10 | " vim: set ts=4 sw=4 tw=78 noet : 11 | 12 | 13 | "---------------------------------------------------------------------- 14 | " internal 15 | "---------------------------------------------------------------------- 16 | let s:has_hlget = exists('*hlget')? 1 : 0 17 | let s:has_hlset = exists('*hlset')? 1 : 0 18 | 19 | 20 | "---------------------------------------------------------------------- 21 | " get highlighting group 22 | "---------------------------------------------------------------------- 23 | function! s:sim_hlget(name) 24 | let error = 0 25 | redir => g:quickui_highlight_tmp 26 | try 27 | exec 'silent hi ' . a:name 28 | catch 29 | let error = 1 30 | endtry 31 | redir END 32 | if error != 0 33 | return [] 34 | endif 35 | let capture = g:quickui_highlight_tmp 36 | let items = [] 37 | for text in split(capture, '\n') 38 | let text = quickui#core#string_strip(text) 39 | if text == '' 40 | continue 41 | endif 42 | let item = {} 43 | let item.name = matchstr(text, '^\w\+') 44 | if item.name == '' 45 | continue 46 | endif 47 | let parts = split(text, ' ') 48 | if empty(parts) 49 | continue 50 | endif 51 | if text =~ ' cleared$' 52 | let item.cleared = v:true 53 | elseif text =~ ' links to \w\+$' 54 | let links = matchstr(text, ' links to \zs\w\+$') 55 | let item.linksto = quickui#core#string_strip(links) 56 | else 57 | for part in parts[1:] 58 | if part =~ '\w\+=' 59 | let key = matchstr(part, '^\w\+') 60 | let val = matchstr(part, '^\w\+=\zs\%(\\.\|\S\)*') 61 | if key == 'term' || key == 'cterm' || key == 'gui' 62 | let opts = {} 63 | for element in split(val, ',') 64 | let opts[element] = v:true 65 | endfor 66 | let item[key] = opts 67 | else 68 | let item[key] = val 69 | endif 70 | elseif part == 'cleared' 71 | endif 72 | endfor 73 | endif 74 | let items += [item] 75 | endfor 76 | return items 77 | endfunc 78 | 79 | 80 | "---------------------------------------------------------------------- 81 | " simulate hlset 82 | "---------------------------------------------------------------------- 83 | function! s:sim_hlset(items) 84 | let skip = {'name':1, 'id':1, 'linksto':1, 'force':1} 85 | for item in a:items 86 | let name = get(item, 'name', '') 87 | if name == '' 88 | continue 89 | endif 90 | let force = get(item, 'force', v:false) 91 | let cmd = (force == 0)? 'hi ' : 'hi! ' 92 | if get(item, 'cleared', v:false) == v:true 93 | exec cmd . 'clear ' . name 94 | else 95 | let part = [] 96 | for key in keys(item) 97 | if has_key(skip, key) == 0 98 | let val = item[key] 99 | if type(val) == v:t_dict 100 | let r = join(keys(val), ',') 101 | else 102 | let r = val 103 | endif 104 | let part += [key . '=' . r] 105 | endif 106 | endfor 107 | let text = cmd . ' ' . name . ' ' . join(part, ' ') 108 | exec text 109 | endif 110 | endfor 111 | endfunc 112 | 113 | 114 | "---------------------------------------------------------------------- 115 | " get highlighting info 116 | "---------------------------------------------------------------------- 117 | function! quickui#highlight#get(name, ...) 118 | let resolve = (a:0 > 0)? (a:1) : 0 119 | if s:has_hlget 120 | " return hlget(a:name, resolve) 121 | endif 122 | if !resolve 123 | return s:sim_hlget(a:name) 124 | endif 125 | let items = [] 126 | for item in s:sim_hlget(a:name) 127 | if has_key(item, 'linksto') == 0 128 | let items += [item] 129 | continue 130 | endif 131 | let info = item 132 | while 1 133 | if has_key(info, 'linksto') == 0 134 | break 135 | endif 136 | let links = info.linksto 137 | let hr = s:sim_hlget(links) 138 | if empty(hr) 139 | break 140 | endif 141 | let info = hr[0] 142 | endwhile 143 | let info.name = item.name 144 | let items += [info] 145 | endfor 146 | return items 147 | endfunc 148 | 149 | 150 | "---------------------------------------------------------------------- 151 | " set highlight group 152 | "---------------------------------------------------------------------- 153 | function! quickui#highlight#set(items) 154 | if s:has_hlset 155 | " return hlset(a:items) 156 | endif 157 | call s:sim_hlset(a:items) 158 | endfunc 159 | 160 | 161 | "---------------------------------------------------------------------- 162 | " clear highlight 163 | "---------------------------------------------------------------------- 164 | function! quickui#highlight#clear(name) 165 | if s:has_hlset 166 | let info = {'name': a:name, 'cleared': v:true} 167 | call hlset([info]) 168 | else 169 | exec 'hi! clear ' . a:name 170 | endif 171 | endfunc 172 | 173 | 174 | "---------------------------------------------------------------------- 175 | " term add feature 176 | "---------------------------------------------------------------------- 177 | function! quickui#highlight#term_add(info, what) 178 | let info = a:info 179 | let what = a:what 180 | if has_key(info, 'term') 181 | if type(info.term) == v:t_dict 182 | let info.term[what] = v:true 183 | elseif type(info.term) == v:t_string 184 | let opts = {} 185 | for key in split(info.term, ',') 186 | let opts[key] = v:true 187 | endfor 188 | let opts[what] = v:true 189 | let info.term = opts 190 | endif 191 | else 192 | let info.term = {} 193 | let info.term[what] = v:true 194 | endif 195 | endfunc 196 | 197 | 198 | "---------------------------------------------------------------------- 199 | " cterm add feature 200 | "---------------------------------------------------------------------- 201 | function! quickui#highlight#cterm_add(info, what) 202 | let info = a:info 203 | let what = a:what 204 | if has_key(info, 'cterm') 205 | if type(info.cterm) == v:t_dict 206 | let info.cterm[what] = v:true 207 | elseif type(info.cterm) == v:t_string 208 | let opts = {} 209 | for key in split(info.cterm, ',') 210 | let opts[key] = v:true 211 | endfor 212 | let opts[what] = v:true 213 | let info.cterm = opts 214 | endif 215 | else 216 | let info.cterm = {} 217 | let info.cterm[what] = v:true 218 | endif 219 | endfunc 220 | 221 | 222 | "---------------------------------------------------------------------- 223 | " gui add feature 224 | "---------------------------------------------------------------------- 225 | function! quickui#highlight#gui_add(info, what) 226 | let info = a:info 227 | let what = a:what 228 | if has_key(info, 'gui') 229 | if type(info.gui) == v:t_dict 230 | let info.gui[what] = v:true 231 | elseif type(info.gui) == v:t_string 232 | let opts = {} 233 | for key in split(info.gui, ',') 234 | let opts[key] = v:true 235 | endfor 236 | let opts[what] = v:true 237 | let info.gui = opts 238 | endif 239 | else 240 | let info.gui = {} 241 | let info.gui[what] = v:true 242 | endif 243 | endfunc 244 | 245 | 246 | "---------------------------------------------------------------------- 247 | " new underline 248 | "---------------------------------------------------------------------- 249 | function! quickui#highlight#grant_underline(info) 250 | let info = a:info 251 | call quickui#highlight#term_add(info, 'underline') 252 | call quickui#highlight#cterm_add(info, 'underline') 253 | call quickui#highlight#gui_add(info, 'underline') 254 | return info 255 | endfunc 256 | 257 | 258 | "---------------------------------------------------------------------- 259 | " add colors 260 | "---------------------------------------------------------------------- 261 | function! quickui#highlight#grant_color(info, colors) 262 | for key in keys(a:colors) 263 | let a:info[key] = a:colors[key] 264 | endfor 265 | return a:info 266 | endfunc 267 | 268 | 269 | "---------------------------------------------------------------------- 270 | " add underline feature 271 | "---------------------------------------------------------------------- 272 | function! quickui#highlight#make_underline(newname, name) 273 | let hr = quickui#highlight#get(a:name, 1) 274 | if len(hr) == 0 275 | return -1 276 | endif 277 | let info = (len(hr) == 0)? {} : hr[0] 278 | call quickui#highlight#term_add(info, 'underline') 279 | call quickui#highlight#cterm_add(info, 'underline') 280 | call quickui#highlight#gui_add(info, 'underline') 281 | if has_key(info, 'id') 282 | unlet info['id'] 283 | endif 284 | let info.name = a:newname 285 | let info.force = v:true 286 | call quickui#highlight#set([info]) 287 | return info 288 | endfunc 289 | 290 | 291 | 292 | "---------------------------------------------------------------------- 293 | " combine foreground and background colors 294 | "---------------------------------------------------------------------- 295 | function! quickui#highlight#overlay(newname, background, foreground) 296 | let hr1 = quickui#highlight#get(a:background, 1) 297 | let hr2 = quickui#highlight#get(a:foreground, 1) 298 | let info1 = empty(hr1)? {} : hr1[0] 299 | let info2 = empty(hr2)? {} : hr2[0] 300 | for key in ['ctermfg', 'guifg'] 301 | if has_key(info2, key) 302 | let info1[key] = info2[key] 303 | endif 304 | endfor 305 | let info1.name = a:newname 306 | let info1.force = v:true 307 | call quickui#highlight#set([info1]) 308 | endfunc 309 | 310 | 311 | -------------------------------------------------------------------------------- /autoload/quickui/input.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " input.vim - 4 | " 5 | " Created by skywind on 2021/11/27 6 | " Last Modified: 2021/11/30 01:50 7 | " 8 | "====================================================================== 9 | 10 | " vim: set noet fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : 11 | 12 | "---------------------------------------------------------------------- 13 | " internal variables 14 | "---------------------------------------------------------------------- 15 | let s:has_nvim = g:quickui#core#has_nvim 16 | let s:history = {} 17 | 18 | 19 | "---------------------------------------------------------------------- 20 | " init 21 | "---------------------------------------------------------------------- 22 | function! s:init_input_box(prompt, opts) 23 | let border = get(a:opts, 'border', g:quickui#style#border) 24 | let hwnd = {} 25 | let head = [] 26 | if type(a:prompt) == v:t_list 27 | let head = deepcopy(a:prompt) 28 | else 29 | let head = split('' . a:prompt, "\n") 30 | endif 31 | let hwnd.h = 2 + len(head) 32 | let hwnd.lnum = 2 + len(head) 33 | if has_key(a:opts, 'w') 34 | let hwnd.w = a:opts.w 35 | else 36 | let limit = 8 37 | for text in head 38 | let width = strdisplaywidth(text) 39 | let limit = (limit < width)? width : limit 40 | endfor 41 | if &columns >= 80 42 | let limit = (limit < 50)? 50 : limit 43 | endif 44 | let hwnd.w = limit 45 | endif 46 | let hwnd.image = head + [' ', repeat(' ', hwnd.w)] 47 | let hwnd.bid = quickui#core#scratch_buffer('input', hwnd.image) 48 | let hwnd.opts = deepcopy(a:opts) 49 | let hwnd.opts.color = get(a:opts, 'color', 'QuickBG') 50 | let hwnd.opts.bordercolor = get(a:opts, 'bordercolor', 'QuickBorder') 51 | let hwnd.opts.text = get(a:opts, 'text', '') 52 | let hwnd.border = border 53 | let title = ' Input ' 54 | let hwnd.rl = quickui#readline#new() 55 | if hwnd.opts.text != '' 56 | call hwnd.rl.set(hwnd.opts.text) 57 | call hwnd.rl.seek(0, 2) 58 | let hwnd.rl.select = 0 59 | endif 60 | let hwnd.pos = 0 61 | let hwnd.wait = get(a:opts, 'wait', 0) 62 | let hwnd.exit = 0 63 | let hwnd.strict = get(a:opts, 'strict', 1) 64 | let hwnd.history = get(hwnd.opts, 'history', '') 65 | if hwnd.history != '' 66 | let key = hwnd.history 67 | let hwnd.rl.history = [''] + get(s:history, key, []) 68 | " echom hwnd.rl.history 69 | endif 70 | if has_key(hwnd.opts, 'row') && has_key(hwnd.opts, 'col') 71 | " pass 72 | else 73 | let ww = hwnd.w 74 | let hh = hwnd.h 75 | let hwnd.opts.col = (&columns - ww) / 2 76 | let hwnd.opts.row = (&lines - hh) / 2 77 | let limit1 = (&lines - 2) * 82 / 100 78 | let limit2 = (&lines - 2) 79 | if hh + 8 < limit1 80 | let hwnd.opts.row = (limit1 - hh) / 2 81 | else 82 | let hwnd.opts.row = (limit2 - hh) / 2 83 | endif 84 | endif 85 | return hwnd 86 | endfunc 87 | 88 | 89 | "---------------------------------------------------------------------- 90 | " create input box object 91 | "---------------------------------------------------------------------- 92 | function! s:vim_create_input(prompt, opts) 93 | let hwnd = s:init_input_box(a:prompt, a:opts) 94 | let opts = {'hidden':1, 'wrap':1} 95 | let opts.minwidth = hwnd.w 96 | let opts.maxwidth = hwnd.w 97 | let opts.minheight = hwnd.h 98 | let opts.minheight = hwnd.h 99 | let winid = popup_create(hwnd.bid, opts) 100 | if has_key(a:opts, 'line') == 0 || has_key(a:opts, 'col') == 0 101 | call quickui#utils#center(winid, 1) 102 | endif 103 | let opts = {'mapping':0, 'cursorline':0, 'drag':1} 104 | let opts.border = [0,0,0,0,0,0,0,0,0] 105 | if hwnd.border > 0 106 | let opts.borderchars = quickui#core#border_vim(hwnd.border) 107 | let opts.border = [1,1,1,1,1,1,1,1,1] 108 | let opts.close = 'button' 109 | endif 110 | let opts.padding = [1,1,1,1] 111 | if has_key(a:opts, 'title') && (a:opts.title != '') 112 | let opts.title = ' ' . a:opts.title . ' ' 113 | endif 114 | let bc = hwnd.opts.bordercolor 115 | let opts.resize = 0 116 | let opts.highlight = hwnd.opts.color 117 | let opts.borderhighlight = [bc, bc, bc, bc] 118 | let opts.callback = function('s:popup_exit') 119 | let hwnd.winid = winid 120 | let local = quickui#core#popup_local(winid) 121 | let local.hwnd = hwnd 122 | call popup_setoptions(winid, opts) 123 | call popup_show(winid) 124 | redraw 125 | return hwnd 126 | endfunc 127 | 128 | 129 | "---------------------------------------------------------------------- 130 | " exit callback 131 | "---------------------------------------------------------------------- 132 | function! s:popup_exit(winid, code) 133 | let local = quickui#core#popup_local(a:winid) 134 | let local.hwnd.exit = 1 135 | endfunc 136 | 137 | 138 | "---------------------------------------------------------------------- 139 | " neovim: create input 140 | "---------------------------------------------------------------------- 141 | function! s:nvim_create_input(prompt, opts) 142 | let hwnd = s:init_input_box(a:prompt, a:opts) 143 | let opts = {'focusable':1, 'style':'minimal', 'relative':'editor'} 144 | let title = ' Input ' 145 | let border = hwnd.border 146 | let back = quickui#utils#make_border(hwnd.w + 2, hwnd.h + 2, border, title, 1) 147 | let hwnd.back = back 148 | let opts.width = hwnd.w 149 | let opts.height = hwnd.h 150 | let opts.row = hwnd.opts.row 151 | let opts.col = hwnd.opts.col 152 | if has('nvim-0.6.0') 153 | let opts.noautocmd = 1 154 | endif 155 | let winid = nvim_open_win(hwnd.bid, 0, opts) 156 | let hwnd.winid = winid 157 | let background = -1 158 | if border > 0 && get(g:, 'quickui_nvim_simulate_border', 1) != 0 159 | let nbid = quickui#core#scratch_buffer('inputborder', back) 160 | let op = {'relative':'editor', 'focusable':1, 'style':'minimal'} 161 | let op.width = hwnd.w + 4 162 | let op.height = hwnd.h + 4 163 | let op.row = hwnd.opts.row - 2 164 | let op.col = hwnd.opts.col - 2 165 | let bordercolor = hwnd.opts.bordercolor 166 | if has('nvim-0.6.0') 167 | let op.noautocmd = 1 168 | endif 169 | let background = nvim_open_win(nbid, 0, op) 170 | call nvim_win_set_option(background, 'winhl', 'Normal:' . bordercolor) 171 | endif 172 | let hwnd.background = background 173 | call nvim_win_set_option(winid, 'winhl', 'Normal:' . hwnd.opts.color) 174 | return hwnd 175 | endfunc 176 | 177 | 178 | "---------------------------------------------------------------------- 179 | " redraw input area 180 | "---------------------------------------------------------------------- 181 | function! s:update_input(hwnd) 182 | let hwnd = a:hwnd 183 | let rl = hwnd.rl 184 | let size = hwnd.w 185 | let ts = float2nr(reltimefloat(reltime()) * 1000) 186 | let blink = rl.blink(ts) 187 | let blink = (hwnd.wait)? 0 : blink 188 | let hwnd.pos = rl.slide(hwnd.pos, size) 189 | let display = rl.render(hwnd.pos, size) 190 | let cmdlist = ['syn clear'] 191 | let x = 1 192 | let y = hwnd.lnum 193 | let content = [] 194 | for [attr, text] in display 195 | let len = strwidth(text) 196 | let content += [text] 197 | let color = 'QuickInput' 198 | if attr == 1 199 | let color = (blink == 0)? 'QuickCursor' : 'QuickInput' 200 | elseif attr == 2 201 | let color = 'QuickVisual' 202 | elseif attr == 3 203 | let color = (blink == 0)? 'QuickCursor' : 'QuickVisual' 204 | endif 205 | let cmd = quickui#core#high_region(color, y, x, y, x + len, 1) 206 | let cmdlist += [cmd] 207 | let x += len 208 | endfor 209 | let text = join(content, '') 210 | call setbufline(hwnd.bid, y, text) 211 | call setbufvar(hwnd.bid, '&modified', 0) 212 | call quickui#core#win_execute(hwnd.winid, cmdlist) 213 | noautocmd redraw 214 | if 0 215 | echon 'blink='. blink 216 | echon ' <' 217 | call rl.echo(blink, 0, hwnd.w) 218 | echon '>' 219 | endif 220 | endfunc 221 | 222 | 223 | "---------------------------------------------------------------------- 224 | " select all text 225 | "---------------------------------------------------------------------- 226 | function! s:select_all(hwnd) 227 | let hwnd = a:hwnd 228 | let rl = hwnd.rl 229 | let hwnd.pos = 0 230 | call rl.seek(0, 2) 231 | if rl.size > 0 232 | let rl.select = 0 233 | endif 234 | let hwnd.pos = rl.slide(hwnd.pos, hwnd.w) 235 | endfunc 236 | 237 | 238 | "---------------------------------------------------------------------- 239 | " create input box 240 | "---------------------------------------------------------------------- 241 | function! quickui#input#create(prompt, opts) 242 | if s:has_nvim == 0 243 | let hwnd = s:vim_create_input(a:prompt, a:opts) 244 | else 245 | let hwnd = s:nvim_create_input(a:prompt, a:opts) 246 | endif 247 | let rl = hwnd.rl 248 | let accept = 0 249 | let result = '' 250 | silent! exec 'nohl' 251 | while hwnd.exit == 0 252 | call s:update_input(hwnd) 253 | try 254 | if hwnd.wait != 0 255 | let code = getchar() 256 | else 257 | let code = getchar(0) 258 | endif 259 | catch /^Vim:Interrupt$/ 260 | let code = "\" 261 | endtry 262 | if type(code) == v:t_number && code == 0 263 | try 264 | exec 'sleep 15m' 265 | continue 266 | catch /^Vim:Interrupt$/ 267 | let code = "\" 268 | endtry 269 | endif 270 | let ch = (type(code) == v:t_number)? nr2char(code) : code 271 | if ch == "\" || ch == "\" 272 | break 273 | endif 274 | if ch == "" 275 | continue 276 | elseif ch == "\" 277 | break 278 | elseif ch == "\" 279 | let result = rl.update() 280 | if result != '' || hwnd.strict == 0 281 | let accept = 1 282 | call rl.history_save() 283 | break 284 | endif 285 | elseif ch == "\" 286 | if v:mouse_winid == hwnd.winid 287 | if v:mouse_lnum == hwnd.lnum 288 | let x = v:mouse_col - (s:has_nvim? 1 : 3) 289 | if x >= 0 && x < hwnd.w 290 | let pos = rl.mouse_click(hwnd.pos, x) 291 | call rl.seek(pos, 0) 292 | let rl.select = -1 293 | endif 294 | endif 295 | elseif s:has_nvim != 0 296 | if v:mouse_winid == hwnd.background 297 | if v:mouse_lnum == 1 298 | if v:mouse_col == hwnd.w + 4 299 | break 300 | endif 301 | endif 302 | endif 303 | endif 304 | elseif ch == "\" || ch == "\" 305 | if len(rl.history) > 0 306 | call rl.feed("\") 307 | call s:select_all(hwnd) 308 | endif 309 | elseif ch == "\" || ch == "\" 310 | if len(rl.history) > 0 311 | call rl.feed("\") 312 | call s:select_all(hwnd) 313 | endif 314 | elseif ch == "\" 315 | redraw 316 | echon "winsize: " . hwnd.w 317 | elseif ch == "\" 318 | call s:select_all(hwnd) 319 | elseif ch == "\" 320 | let rop = {} 321 | let text = quickui#utils#read_eval(rop) 322 | let text = split(text, "\n", 1)[0] 323 | let text = substitute(text, '[\r\n\t]', ' ', 'g') 324 | if text != '' 325 | if rl.select >= 0 326 | call rl.visual_delete() 327 | endif 328 | call rl.insert(text) 329 | endif 330 | else 331 | call rl.feed(ch) 332 | endif 333 | endwhile 334 | if s:has_nvim == 0 335 | call popup_close(hwnd.winid) 336 | else 337 | call nvim_win_close(hwnd.winid, 0) 338 | if hwnd.background >= 0 339 | call nvim_win_close(hwnd.background, 0) 340 | endif 341 | endif 342 | call quickui#core#popup_clear(hwnd.winid) 343 | redraw 344 | if hwnd.history != '' 345 | let s:history[hwnd.history] = deepcopy(rl.history) 346 | endif 347 | return result 348 | endfunc 349 | 350 | 351 | "---------------------------------------------------------------------- 352 | " open input box 353 | "---------------------------------------------------------------------- 354 | function! quickui#input#open(prompt, ...) 355 | let opts = {'title':'Input'} 356 | let opts.text = (a:0 >= 1)? (a:1) : '' 357 | if (a:0 >= 2) 358 | let opts.history = a:2 359 | endif 360 | let opts.wait = get(g:, 'quickui_input_wait', 0) 361 | return quickui#input#create(a:prompt, opts) 362 | endfunc 363 | 364 | 365 | "---------------------------------------------------------------------- 366 | " testing suit 367 | "---------------------------------------------------------------------- 368 | if 0 369 | let opts = {} 370 | let opts.title = 'Input' 371 | " let opts.w = 50 372 | echo quickui#input#open("Enter your name:", 'haha', 'abc') 373 | endif 374 | 375 | 376 | -------------------------------------------------------------------------------- /autoload/quickui/listbox.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " listbox.vim - 4 | " 5 | " Created by skywind on 2019/12/20 6 | " Last Modified: 2023/08/30 14:47 7 | " 8 | "====================================================================== 9 | 10 | " vim: set noet fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : 11 | 12 | "---------------------------------------------------------------------- 13 | " stats 14 | "---------------------------------------------------------------------- 15 | 16 | " last position 17 | let g:quickui#listbox#cursor = -1 18 | 19 | 20 | "---------------------------------------------------------------------- 21 | " parse 22 | "---------------------------------------------------------------------- 23 | function! quickui#listbox#parse(textlist) 24 | let items = {'image': [], 'column':0, 'nrows':0, 'keys':[], 'cmds':[]} 25 | let items.keymap = {} 26 | let items.displaywidth = 0 27 | let sizes = [] 28 | let objects = [] 29 | let spliter = ' ' 30 | for description in a:textlist 31 | let obj = quickui#core#single_parse(description) 32 | let objects += [obj] 33 | if obj.key_pos >= 0 34 | let items.keymap[tolower(obj.key_char)] = items.nrows 35 | endif 36 | let items.nrows += 1 37 | while len(sizes) < obj.size 38 | let sizes += [0] 39 | endwhile 40 | let items.column = len(sizes) 41 | let index = 0 42 | for part in obj.part 43 | let size = strdisplaywidth(obj.part[index]) 44 | if size > sizes[index] 45 | let sizes[index] = size 46 | endif 47 | let index += 1 48 | endfor 49 | endfor 50 | for obj in objects 51 | let start = 1 52 | let index = 0 53 | let output = ' ' 54 | let ni = ['', -1] 55 | for part in obj.part 56 | let size = strdisplaywidth(part) 57 | let need = sizes[index] 58 | if size >= need 59 | let element = part 60 | else 61 | let element = part . repeat(' ', need - size) 62 | endif 63 | if obj.key_idx == index 64 | let ni[0] = obj.key_char 65 | let ni[1] = start + obj.key_pos 66 | endif 67 | let output .= element 68 | if index + 1 < len(obj.part) 69 | let output .= spliter 70 | endif 71 | let start += strchars(element) + strchars(spliter) 72 | let index += 1 73 | endfor 74 | let items.image += [output . ' '] 75 | let items.keys += [ni] 76 | let items.cmds += [obj.cmd] 77 | let size = strdisplaywidth(output) + 1 78 | if size > items.displaywidth 79 | let items.displaywidth = size 80 | endif 81 | endfor 82 | return items 83 | endfunc 84 | 85 | 86 | "---------------------------------------------------------------------- 87 | " reposition text offset 88 | "---------------------------------------------------------------------- 89 | function! quickui#listbox#reposition() 90 | exec 'normal! zz' 91 | let height = winheight(0) 92 | let size = line('$') 93 | let curline = line('.') 94 | let winline = winline() 95 | let topline = curline - winline + 1 96 | let botline = topline + height - 1 97 | let disline = botline - size 98 | if disline > 0 99 | exec 'normal ggG' 100 | exec ':' . curline 101 | exec 'normal G' 102 | exec ':' . curline 103 | endif 104 | endfunc 105 | 106 | 107 | "---------------------------------------------------------------------- 108 | " highlight keys 109 | "---------------------------------------------------------------------- 110 | function! s:highlight_keys(winid, items) 111 | let items = a:items 112 | let index = 0 113 | let cmdlist = [] 114 | while index < items.nrows 115 | let key = items.keys[index] 116 | if key[1] >= 0 117 | let px = key[1] + 1 118 | let py = index + 1 119 | let cmd = quickui#core#high_region('QuickKey', py, px, py, px + 1, 1) 120 | let cmdlist += [cmd] 121 | endif 122 | let index += 1 123 | endwhile 124 | call quickui#core#win_execute(a:winid, cmdlist) 125 | endfunc 126 | 127 | 128 | "---------------------------------------------------------------------- 129 | " init window 130 | "---------------------------------------------------------------------- 131 | function! s:vim_create_listbox(textlist, opts) 132 | let hwnd = {} 133 | let opts = {} 134 | let items = quickui#listbox#parse(a:textlist) 135 | let winid = popup_create(items.image, {'hidden':1, 'wrap':0}) 136 | let bufnr = winbufnr(winid) 137 | let hwnd.winid = winid 138 | let hwnd.items = items 139 | let hwnd.bufnr = bufnr 140 | let hwnd.keymap = quickui#utils#keymap() 141 | let hwnd.hotkey = items.keymap 142 | let hwnd.opts = deepcopy(a:opts) 143 | let hwnd.context = has_key(a:opts, 'context')? a:opts.context : {} 144 | let minsize = strdisplaywidth(get(a:opts, 'title', '')) 145 | let minsize = max([items.displaywidth, minsize]) 146 | let border = get(a:opts, 'border', g:quickui#style#border) 147 | let w = has_key(a:opts, 'w')? a:opts.w : minsize 148 | let h = has_key(a:opts, 'h')? a:opts.h : items.nrows 149 | if h + 6 > &lines 150 | let h = &lines - 6 151 | let h = (h < 1)? 1 : h 152 | endif 153 | if w + 4 > &columns 154 | let w = &columns - 4 155 | let w = (w < 1)? 1 : w 156 | endif 157 | let opts = {"minwidth":w, "minheight":h, "maxwidth":w, "maxheight":h} 158 | let ww = w + ((border != 0)? 2 : 0) 159 | let hh = h + ((border != 0)? 2 : 0) 160 | if has_key(a:opts, 'line') 161 | let opts.line = a:opts.line 162 | else 163 | let limit1 = (&lines - 2) * 90 / 100 164 | let limit2 = (&lines - 2) 165 | if h + 4 < limit1 166 | let opts.line = (limit1 - hh) / 2 167 | else 168 | let opts.line = (limit2 - hh) / 2 169 | endif 170 | let opts.line = (opts.line < 1)? 1 : opts.line 171 | endif 172 | if has_key(a:opts, 'col') 173 | let opts.col = a:opts.col 174 | else 175 | let opts.col = (&columns - ww) / 2 176 | let opts.col = (opts.col < 1)? 1 : opts.col 177 | endif 178 | call popup_move(winid, opts) 179 | call setwinvar(winid, '&wincolor', get(a:opts, 'color', 'QuickBG')) 180 | if get(a:opts, 'index', 0) >= 0 181 | let moveto = get(a:opts, 'index', 0) + 1 182 | call popup_show(winid) 183 | call win_execute(winid, 'normal! G') 184 | call win_execute(winid, ':' . moveto) 185 | call win_execute(winid, 'normal! G') 186 | call win_execute(winid, ':' . moveto) 187 | call win_execute(winid, 'call quickui#listbox#reposition()') 188 | endif 189 | let opts = {'cursorline':1, 'drag':1, 'mapping':0} 190 | if get(a:opts, 'manual', 0) == 0 191 | let opts.filter = function('s:popup_filter') 192 | let opts.callback = function('s:popup_exit') 193 | endif 194 | let opts.border = [0,0,0,0,0,0,0,0,0] 195 | if border > 0 196 | let opts.borderchars = quickui#core#border_vim(border) 197 | let opts.border = [1,1,1,1,1,1,1,1,1] 198 | endif 199 | if has_key(a:opts, 'title') && (a:opts.title != '') 200 | let opts.title = ' ' . a:opts.title . ' ' 201 | endif 202 | let opts.padding = [0,1,0,1] 203 | if has_key(a:opts, 'close') && (a:opts.close != '') 204 | let opts.close = a:opts.close 205 | endif 206 | let local = quickui#core#popup_local(winid) 207 | let local.hwnd = hwnd 208 | let local.winid = winid 209 | let keymap = hwnd.keymap 210 | if !has_key(a:opts, 'horizon') 211 | let keymap["\"] = 'HALFUP' 212 | let keymap["\"] = 'HALFDOWN' 213 | let keymap["h"] = 'HALFUP' 214 | let keymap["l"] = 'HALFDOWN' 215 | endif 216 | if has_key(a:opts, 'keymap') 217 | for key in keys(a:opts.keymap) 218 | let keymap[key] = a:opts.keymap[key] 219 | endfor 220 | endif 221 | let hwnd.state = 1 222 | let hwnd.code = 0 223 | let hwnd.tag = '' 224 | let bc = get(a:opts, 'bordercolor', 'QuickBorder') 225 | let opts.borderhighlight = [bc, bc, bc, bc] 226 | call popup_setoptions(winid, opts) 227 | call win_execute(winid, 'syn clear') 228 | if has_key(a:opts, 'syntax') 229 | call win_execute(winid, 'set ft=' . fnameescape(a:opts.syntax)) 230 | endif 231 | " call s:highlight_keys(winid, items) 232 | call s:highlight_keys(winid, items) 233 | call popup_show(winid) 234 | return hwnd 235 | endfunc 236 | 237 | 238 | "---------------------------------------------------------------------- 239 | " close list box 240 | "---------------------------------------------------------------------- 241 | function! quickui#listbox#close(hwnd) 242 | if a:hwnd.winid > 0 243 | call popup_close(a:hwnd.winid) 244 | call quickui#core#popup_clear(a:hwnd.winid) 245 | let a:hwnd.winid = -1 246 | endif 247 | endfunc 248 | 249 | 250 | "---------------------------------------------------------------------- 251 | " handle exit code 252 | "---------------------------------------------------------------------- 253 | function! s:popup_exit(winid, code) 254 | let local = quickui#core#popup_local(a:winid) 255 | let hwnd = local.hwnd 256 | let code = a:code 257 | if a:code > 0 258 | call win_execute(a:winid, ':' . a:code) 259 | redraw 260 | let code = a:code - 1 261 | endif 262 | let hwnd.state = 0 263 | let hwnd.code = code 264 | let g:quickui#listbox#cursor = quickui#utils#get_cursor(a:winid) - 1 265 | call quickui#core#popup_clear(a:winid) 266 | silent! call popup_hide(a:winid) 267 | let g:quickui#listbox#current = hwnd 268 | if has_key(hwnd.opts, 'callback') 269 | call call(hwnd.opts.callback, [code]) 270 | endif 271 | if code >= 0 && code < hwnd.items.nrows 272 | let cmd = hwnd.items.cmds[code] 273 | if cmd != '' 274 | redraw 275 | try 276 | exec cmd 277 | catch /.*/ 278 | echohl Error 279 | echom v:exception 280 | echohl None 281 | endtry 282 | endif 283 | endif 284 | endfunc 285 | 286 | 287 | "---------------------------------------------------------------------- 288 | " key processing 289 | "---------------------------------------------------------------------- 290 | function! s:popup_filter(winid, key) 291 | let local = quickui#core#popup_local(a:winid) 292 | let hwnd = local.hwnd 293 | let keymap = hwnd.keymap 294 | if a:key == "\" || a:key == "\" 295 | call popup_close(a:winid, -1) 296 | return 1 297 | elseif a:key == "\" || a:key == "\" 298 | return popup_filter_menu(a:winid, "\") 299 | elseif a:key == "\" 300 | let pos = getmousepos() 301 | if pos.winid == a:winid 302 | if pos.line > 0 303 | call win_execute(a:winid, ':' . pos.line) 304 | call popup_setoptions(a:winid, {}) 305 | redraw 306 | return popup_filter_menu(a:winid, "\") 307 | endif 308 | endif 309 | elseif a:key == ':' || a:key == '/' || a:key == '?' 310 | call quickui#utils#search_or_jump(a:winid, a:key) 311 | return 1 312 | elseif has_key(hwnd.hotkey, a:key) 313 | let index = hwnd.hotkey[a:key] 314 | call popup_close(a:winid, index + 1) 315 | return 1 316 | elseif has_key(keymap, a:key) 317 | let key = keymap[a:key] 318 | if strpart(key, 0, 4) == 'TAG:' 319 | let hwnd.tag = strpart(key, 4) 320 | return popup_filter_menu(a:winid, "\") 321 | elseif key == 'ESC' 322 | call popup_close(a:winid, -1) 323 | return 1 324 | elseif key == 'NEXT' || key == 'PREV' 325 | call quickui#utils#search_next(a:winid, key) 326 | else 327 | let cmd = 'quickui#listbox#cursor_movement("' . key . '")' 328 | call win_execute(a:winid, 'call ' . cmd) 329 | return 1 330 | endif 331 | endif 332 | return popup_filter_menu(a:winid, a:key) 333 | endfunc 334 | 335 | 336 | "---------------------------------------------------------------------- 337 | " how to move cursor 338 | "---------------------------------------------------------------------- 339 | function! quickui#listbox#cursor_movement(where) 340 | let curline = line('.') 341 | let endline = line('$') 342 | let height = winheight('.') 343 | if a:where == 'TOP' 344 | let curline = 0 345 | elseif a:where == 'BOTTOM' 346 | let curline = line('$') 347 | elseif a:where == 'UP' 348 | let curline = curline - 1 349 | elseif a:where == 'DOWN' 350 | let curline = curline + 1 351 | elseif a:where == 'PAGEUP' 352 | let curline = curline - height 353 | elseif a:where == 'PAGEDOWN' 354 | let curline = curline + height 355 | elseif a:where == 'HALFUP' 356 | let curline = curline - height / 2 357 | elseif a:where == 'HALFDOWN' 358 | let curline = curline + height / 2 359 | elseif a:where == 'KEEP' 360 | endif 361 | if curline < 1 362 | let curline = 1 363 | elseif curline > endline 364 | let curline = endline 365 | endif 366 | noautocmd exec ":" . curline 367 | noautocmd exec "normal! 0" 368 | endfunc 369 | 370 | 371 | "---------------------------------------------------------------------- 372 | " block and return result 373 | "---------------------------------------------------------------------- 374 | function! quickui#listbox#inputlist(textlist, opts) 375 | if g:quickui#core#has_nvim != 0 376 | let opts = deepcopy(a:opts) 377 | if has_key(opts, 'callback') 378 | unlet opts['callback'] 379 | endif 380 | return s:nvim_create_listbox(a:textlist, opts) 381 | endif 382 | let opts = deepcopy(a:opts) 383 | let opts.manual = 1 384 | if has_key(opts, 'callback') 385 | call remove(opts, 'callback') 386 | endif 387 | if len(a:textlist) == 0 388 | return -1000 389 | endif 390 | let hwnd = s:vim_create_listbox(a:textlist, opts) 391 | let winid = hwnd.winid 392 | let hr = -1 393 | " call win_execute(winid, 'normal zz') 394 | call popup_show(winid) 395 | while 1 396 | redraw 397 | try 398 | let code = getchar() 399 | catch /^Vim:Interrupt$/ 400 | let code = "\" 401 | endtry 402 | let ch = (type(code) == v:t_number)? nr2char(code) : code 403 | if ch == "\" || ch == "\" 404 | break 405 | elseif ch == " " || ch == "\" 406 | let cmd = 'let g:quickui#listbox#index = line(".")' 407 | call win_execute(winid, cmd) 408 | let hr = g:quickui#listbox#index - 1 409 | break 410 | elseif ch == "\" 411 | let pos = getmousepos() 412 | if pos.winid == winid 413 | if pos.line > 0 414 | call win_execute(winid, ':' . pos.line) 415 | call popup_setoptions(winid, {}) 416 | redraw 417 | let hr = pos.line - 1 418 | break 419 | endif 420 | endif 421 | elseif ch == ':' || ch == '/' || ch == '?' 422 | call quickui#utils#search_or_jump(winid, ch) 423 | call popup_hide(winid) 424 | call popup_show(winid) 425 | elseif has_key(hwnd.hotkey, ch) 426 | let hr = hwnd.hotkey[ch] 427 | if hr >= 0 428 | break 429 | endif 430 | elseif has_key(hwnd.keymap, ch) 431 | let key = hwnd.keymap[ch] 432 | if key == 'ESC' 433 | break 434 | elseif key == 'NEXT' || key == 'PREV' 435 | call quickui#utils#search_next(winid, key) 436 | call popup_hide(winid) 437 | call popup_show(winid) 438 | else 439 | let cmd = 'quickui#listbox#cursor_movement("' . key . '")' 440 | call win_execute(winid, 'call ' . cmd) 441 | call popup_hide(winid) 442 | call popup_show(winid) 443 | endif 444 | endif 445 | endwhile 446 | " echo 'size: '. winheight(winid) 447 | if hr > 0 448 | call quickui#core#win_execute(winid, ':' . (hr + 1)) 449 | redraw 450 | endif 451 | let g:quickui#listbox#cursor = quickui#utils#get_cursor(winid) - 1 452 | call quickui#listbox#close(hwnd) 453 | return hr 454 | endfunc 455 | 456 | 457 | "---------------------------------------------------------------------- 458 | " create list box in neovim 459 | "---------------------------------------------------------------------- 460 | function! s:nvim_create_listbox(textlist, opts) 461 | let hwnd = {} 462 | let opts = {} 463 | let items = quickui#listbox#parse(a:textlist) 464 | let bid = quickui#core#scratch_buffer('listbox', items.image) 465 | let hwnd.items = items 466 | let hwnd.bid = bid 467 | let hwnd.keymap = quickui#utils#keymap() 468 | let hwnd.hotkey = items.keymap 469 | let hwnd.opts = deepcopy(a:opts) 470 | let hwnd.context = has_key(a:opts, 'context')? a:opts.context : {} 471 | let border = get(a:opts, 'border', g:quickui#style#border) 472 | let minsize = strdisplaywidth(get(a:opts, 'title', '')) 473 | let minsize = max([items.displaywidth, minsize]) 474 | let w = has_key(a:opts, 'w')? a:opts.w : minsize + 2 475 | let h = has_key(a:opts, 'h')? a:opts.h : items.nrows 476 | if h + 6 > &lines 477 | let h = &lines - 6 478 | let h = (h < 1)? 1 : h 479 | endif 480 | if w + 4 > &columns 481 | let w = &columns - 4 482 | let w = (w < 1)? 1 : w 483 | endif 484 | let ww = w + ((border != 0)? 2 : 0) 485 | let hh = h + ((border != 0)? 2 : 0) 486 | let opts = {'width':w, 'height':h, 'focusable':1, 'style':'minimal'} 487 | let opts.relative = 'editor' 488 | if has_key(a:opts, 'line') 489 | let opts.row = a:opts.line - 1 490 | else 491 | let limit1 = (&lines - 2) * 90 / 100 492 | let limit2 = (&lines - 2) 493 | " echom printf("limit1=%d limit2=%d h=%d hh=%d", limit1, limit2, h, hh) 494 | if h + 4 < limit1 495 | let opts.row = (limit1 - hh) / 2 496 | else 497 | let opts.row = (limit2 - hh) / 2 498 | endif 499 | let opts.row = (opts.row < 0)? 0 : opts.row 500 | endif 501 | if has_key(a:opts, 'col') 502 | let opts.col = a:opts.col - 1 503 | else 504 | let opts.col = (&columns - ww) / 2 - 1 505 | let opts.col = (opts.col < 0)? 0 : opts.col 506 | endif 507 | let border = get(a:opts, 'border', g:quickui#style#border) 508 | let background = -1 509 | let hwnd.opts.color = get(a:opts, 'color', 'QuickBG') 510 | let color = hwnd.opts.color 511 | if border > 0 && get(g:, 'quickui_nvim_simulate_border', 1) != 0 512 | let opts.row += 1 513 | let opts.col += 1 514 | endif 515 | if has('nvim-0.6.0') 516 | let opts.noautocmd = 1 517 | endif 518 | let winid = nvim_open_win(bid, 0, opts) 519 | let button = (get(a:opts, 'close', '') == 'button')? 1 : 0 520 | if border > 0 && get(g:, 'quickui_nvim_simulate_border', 1) != 0 521 | let title = has_key(a:opts, 'title')? ' ' . a:opts.title . ' ' : '' 522 | let back = quickui#utils#make_border(w, h, border, title, button) 523 | let nbid = quickui#core#scratch_buffer('listborder', back) 524 | let op = {'relative':'editor', 'focusable':1, 'style':'minimal'} 525 | let op.width = w + 2 526 | let op.height = h + 2 527 | let op.row = opts.row - 1 528 | let op.col = opts.col - 1 529 | let bordercolor = get(a:opts, 'bordercolor', 'QuickBorder') 530 | if has('nvim-0.6.0') 531 | let op.noautocmd = 1 532 | endif 533 | let background = nvim_open_win(nbid, 0, op) 534 | call nvim_win_set_option(background, 'winhl', 'Normal:'. bordercolor) 535 | endif 536 | let hwnd.winid = winid 537 | call nvim_win_set_option(winid, 'winhl', 'Normal:'. color) 538 | if get(a:opts, 'index', 0) >= 0 539 | let moveto = get(a:opts, 'index', 0) + 1 540 | call quickui#core#win_execute(winid, 'noautocmd normal! ggG') 541 | call quickui#core#win_execute(winid, 'noautocmd :' . moveto) 542 | call quickui#core#win_execute(winid, 'noautocmd normal! 0') 543 | endif 544 | let border = get(a:opts, 'border', 1) 545 | let keymap = hwnd.keymap 546 | if !has_key(a:opts, 'horizon') 547 | let keymap["\"] = 'HALFUP' 548 | let keymap["\"] = 'HALFDOWN' 549 | let keymap["h"] = 'HALFUP' 550 | let keymap["l"] = 'HALFDOWN' 551 | endif 552 | if has_key(a:opts, 'keymap') 553 | for key in keys(a:opts.keymap) 554 | let keymap[key] = a:opts.keymap[key] 555 | endfor 556 | endif 557 | let hwnd.state = 1 558 | let hwnd.code = 0 559 | let hwnd.tag = '' 560 | call quickui#core#win_execute(winid, 'setlocal nowrap') 561 | call quickui#core#win_execute(winid, 'syn clear') 562 | if has_key(a:opts, 'syntax') 563 | let syntax = fnameescape(a:opts.syntax) 564 | call quickui#core#win_execute(winid, 'set ft=' . syntax) 565 | endif 566 | call s:highlight_keys(winid, items) 567 | call quickui#core#win_execute(winid, "setlocal cursorline scrolloff=0") 568 | if exists('+cursorlineopt') 569 | call quickui#core#win_execute(winid, "setlocal cursorlineopt=both") 570 | endif 571 | let retval = -1 572 | while 1 573 | noautocmd redraw! 574 | try 575 | let code = getchar() 576 | catch /^Vim:Interrupt$/ 577 | let code = "\" 578 | endtry 579 | let ch = (type(code) == v:t_number)? nr2char(code) : code 580 | if ch == "\" || ch == "\" 581 | break 582 | elseif ch == "\" || ch == "\" 583 | let retval = quickui#utils#get_cursor(winid) - 1 584 | break 585 | elseif ch == "\" 586 | if v:mouse_winid == winid 587 | if v:mouse_lnum > 0 588 | let cmd = ':' . v:mouse_lnum 589 | call quickui#core#win_execute(winid, cmd) 590 | redraw! 591 | sleep 10m 592 | let retval = v:mouse_lnum - 1 593 | break 594 | endif 595 | elseif v:mouse_winid == background 596 | if button != 0 && v:mouse_lnum == 1 597 | if v:mouse_col == w + 2 598 | break 599 | endif 600 | endif 601 | endif 602 | elseif ch == ':' || ch == '/' || ch == '?' 603 | call quickui#utils#search_or_jump(winid, ch) 604 | let cmd = 'call quickui#listbox#cursor_movement("KEEP")' 605 | noautocmd call quickui#core#win_execute(winid, cmd) 606 | elseif has_key(hwnd.hotkey, ch) 607 | let retval = hwnd.hotkey[ch] 608 | break 609 | elseif has_key(keymap, ch) 610 | let key = keymap[ch] 611 | if strpart(key, 0, 4) == 'TAG:' 612 | let hwnd.tag = strpart(key, 4) 613 | let retval = quickui#utils#get_cursor(winid) - 1 614 | break 615 | elseif key == "ESC" 616 | break 617 | elseif key == 'NEXT' || key == 'PREV' 618 | call quickui#utils#search_next(winid, key) 619 | else 620 | let cmd = 'quickui#listbox#cursor_movement("' . key . '")' 621 | noautocmd call quickui#core#win_execute(winid, 'call ' . cmd) 622 | endif 623 | endif 624 | endwhile 625 | let hwnd.code = retval 626 | if retval > 0 627 | call quickui#core#win_execute(winid, ':' . (retval + 1)) 628 | endif 629 | let g:quickui#listbox#cursor = quickui#utils#get_cursor(winid) - 1 630 | call nvim_win_close(winid, 0) 631 | if background >= 0 632 | call nvim_win_close(background, 0) 633 | endif 634 | redraw! 635 | let hwnd.state = 0 636 | let g:quickui#listbox#current = hwnd 637 | if has_key(hwnd.opts, 'callback') 638 | call call(hwnd.opts.callback, [retval]) 639 | endif 640 | if retval >= 0 && retval < hwnd.items.nrows 641 | let cmd = hwnd.items.cmds[retval] 642 | if cmd != '' 643 | try 644 | exec cmd 645 | catch /.*/ 646 | echohl Error 647 | echom v:exception 648 | echohl None 649 | endtry 650 | endif 651 | endif 652 | return retval 653 | endfunc 654 | 655 | 656 | "---------------------------------------------------------------------- 657 | " open popup and run command when select an item 658 | "---------------------------------------------------------------------- 659 | function! quickui#listbox#open(content, opts) 660 | if g:quickui#core#has_nvim == 0 661 | return s:vim_create_listbox(a:content, a:opts) 662 | else 663 | return s:nvim_create_listbox(a:content, a:opts) 664 | endif 665 | endfunc 666 | 667 | 668 | 669 | -------------------------------------------------------------------------------- /autoload/quickui/palette9.vim: -------------------------------------------------------------------------------- 1 | vim9script 2 | 3 | #---------------------------------------------------------------------- 4 | # terminal palette of 256 colors 5 | #---------------------------------------------------------------------- 6 | final color_definition = [ 7 | \ { 'color': 0, 'name': 'Black', 'hex': '#000000' }, 8 | \ { 'color': 1, 'name': 'Maroon', 'hex': '#800000' }, 9 | \ { 'color': 2, 'name': 'Green', 'hex': '#008000' }, 10 | \ { 'color': 3, 'name': 'Olive', 'hex': '#808000' }, 11 | \ { 'color': 4, 'name': 'Navy', 'hex': '#000080' }, 12 | \ { 'color': 5, 'name': 'Purple', 'hex': '#800080' }, 13 | \ { 'color': 6, 'name': 'Teal', 'hex': '#008080' }, 14 | \ { 'color': 7, 'name': 'Silver', 'hex': '#c0c0c0' }, 15 | \ { 'color': 8, 'name': 'Grey', 'hex': '#808080' }, 16 | \ { 'color': 9, 'name': 'Red', 'hex': '#ff0000' }, 17 | \ { 'color': 10, 'name': 'Lime', 'hex': '#00ff00' }, 18 | \ { 'color': 11, 'name': 'Yellow', 'hex': '#ffff00' }, 19 | \ { 'color': 12, 'name': 'Blue', 'hex': '#0000ff' }, 20 | \ { 'color': 13, 'name': 'Fuchsia', 'hex': '#ff00ff' }, 21 | \ { 'color': 14, 'name': 'Aqua', 'hex': '#00ffff' }, 22 | \ { 'color': 15, 'name': 'White', 'hex': '#ffffff' }, 23 | \ { 'color': 16, 'name': 'Grey0', 'hex': '#000000' }, 24 | \ { 'color': 17, 'name': 'NavyBlue', 'hex': '#00005f' }, 25 | \ { 'color': 18, 'name': 'DarkBlue', 'hex': '#000087' }, 26 | \ { 'color': 19, 'name': 'Blue3', 'hex': '#0000af' }, 27 | \ { 'color': 20, 'name': 'Blue3', 'hex': '#0000d7' }, 28 | \ { 'color': 21, 'name': 'Blue1', 'hex': '#0000ff' }, 29 | \ { 'color': 22, 'name': 'DarkGreen', 'hex': '#005f00' }, 30 | \ { 'color': 23, 'name': 'DeepSkyBlue4', 'hex': '#005f5f' }, 31 | \ { 'color': 24, 'name': 'DeepSkyBlue4', 'hex': '#005f87' }, 32 | \ { 'color': 25, 'name': 'DeepSkyBlue4', 'hex': '#005faf' }, 33 | \ { 'color': 26, 'name': 'DodgerBlue3', 'hex': '#005fd7' }, 34 | \ { 'color': 27, 'name': 'DodgerBlue2', 'hex': '#005fff' }, 35 | \ { 'color': 28, 'name': 'Green4', 'hex': '#008700' }, 36 | \ { 'color': 29, 'name': 'SpringGreen4', 'hex': '#00875f' }, 37 | \ { 'color': 30, 'name': 'Turquoise4', 'hex': '#008787' }, 38 | \ { 'color': 31, 'name': 'DeepSkyBlue3', 'hex': '#0087af' }, 39 | \ { 'color': 32, 'name': 'DeepSkyBlue3', 'hex': '#0087d7' }, 40 | \ { 'color': 33, 'name': 'DodgerBlue1', 'hex': '#0087ff' }, 41 | \ { 'color': 34, 'name': 'Green3', 'hex': '#00af00' }, 42 | \ { 'color': 35, 'name': 'SpringGreen3', 'hex': '#00af5f' }, 43 | \ { 'color': 36, 'name': 'DarkCyan', 'hex': '#00af87' }, 44 | \ { 'color': 37, 'name': 'LightSeaGreen', 'hex': '#00afaf' }, 45 | \ { 'color': 38, 'name': 'DeepSkyBlue2', 'hex': '#00afd7' }, 46 | \ { 'color': 39, 'name': 'DeepSkyBlue1', 'hex': '#00afff' }, 47 | \ { 'color': 40, 'name': 'Green3', 'hex': '#00d700' }, 48 | \ { 'color': 41, 'name': 'SpringGreen3', 'hex': '#00d75f' }, 49 | \ { 'color': 42, 'name': 'SpringGreen2', 'hex': '#00d787' }, 50 | \ { 'color': 43, 'name': 'Cyan3', 'hex': '#00d7af' }, 51 | \ { 'color': 44, 'name': 'DarkTurquoise', 'hex': '#00d7d7' }, 52 | \ { 'color': 45, 'name': 'Turquoise2', 'hex': '#00d7ff' }, 53 | \ { 'color': 46, 'name': 'Green1', 'hex': '#00ff00' }, 54 | \ { 'color': 47, 'name': 'SpringGreen2', 'hex': '#00ff5f' }, 55 | \ { 'color': 48, 'name': 'SpringGreen1', 'hex': '#00ff87' }, 56 | \ { 'color': 49, 'name': 'MediumSpringGreen', 'hex': '#00ffaf' }, 57 | \ { 'color': 50, 'name': 'Cyan2', 'hex': '#00ffd7' }, 58 | \ { 'color': 51, 'name': 'Cyan1', 'hex': '#00ffff' }, 59 | \ { 'color': 52, 'name': 'DarkRed', 'hex': '#5f0000' }, 60 | \ { 'color': 53, 'name': 'DeepPink4', 'hex': '#5f005f' }, 61 | \ { 'color': 54, 'name': 'Purple4', 'hex': '#5f0087' }, 62 | \ { 'color': 55, 'name': 'Purple4', 'hex': '#5f00af' }, 63 | \ { 'color': 56, 'name': 'Purple3', 'hex': '#5f00d7' }, 64 | \ { 'color': 57, 'name': 'BlueViolet', 'hex': '#5f00ff' }, 65 | \ { 'color': 58, 'name': 'Orange4', 'hex': '#5f5f00' }, 66 | \ { 'color': 59, 'name': 'Grey37', 'hex': '#5f5f5f' }, 67 | \ { 'color': 60, 'name': 'MediumPurple4', 'hex': '#5f5f87' }, 68 | \ { 'color': 61, 'name': 'SlateBlue3', 'hex': '#5f5faf' }, 69 | \ { 'color': 62, 'name': 'SlateBlue3', 'hex': '#5f5fd7' }, 70 | \ { 'color': 63, 'name': 'RoyalBlue1', 'hex': '#5f5fff' }, 71 | \ { 'color': 64, 'name': 'Chartreuse4', 'hex': '#5f8700' }, 72 | \ { 'color': 65, 'name': 'DarkSeaGreen4', 'hex': '#5f875f' }, 73 | \ { 'color': 66, 'name': 'PaleTurquoise4', 'hex': '#5f8787' }, 74 | \ { 'color': 67, 'name': 'SteelBlue', 'hex': '#5f87af' }, 75 | \ { 'color': 68, 'name': 'SteelBlue3', 'hex': '#5f87d7' }, 76 | \ { 'color': 69, 'name': 'CornflowerBlue', 'hex': '#5f87ff' }, 77 | \ { 'color': 70, 'name': 'Chartreuse3', 'hex': '#5faf00' }, 78 | \ { 'color': 71, 'name': 'DarkSeaGreen4', 'hex': '#5faf5f' }, 79 | \ { 'color': 72, 'name': 'CadetBlue', 'hex': '#5faf87' }, 80 | \ { 'color': 73, 'name': 'CadetBlue', 'hex': '#5fafaf' }, 81 | \ { 'color': 74, 'name': 'SkyBlue3', 'hex': '#5fafd7' }, 82 | \ { 'color': 75, 'name': 'SteelBlue1', 'hex': '#5fafff' }, 83 | \ { 'color': 76, 'name': 'Chartreuse3', 'hex': '#5fd700' }, 84 | \ { 'color': 77, 'name': 'PaleGreen3', 'hex': '#5fd75f' }, 85 | \ { 'color': 78, 'name': 'SeaGreen3', 'hex': '#5fd787' }, 86 | \ { 'color': 79, 'name': 'Aquamarine3', 'hex': '#5fd7af' }, 87 | \ { 'color': 80, 'name': 'MediumTurquoise', 'hex': '#5fd7d7' }, 88 | \ { 'color': 81, 'name': 'SteelBlue1', 'hex': '#5fd7ff' }, 89 | \ { 'color': 82, 'name': 'Chartreuse2', 'hex': '#5fff00' }, 90 | \ { 'color': 83, 'name': 'SeaGreen2', 'hex': '#5fff5f' }, 91 | \ { 'color': 84, 'name': 'SeaGreen1', 'hex': '#5fff87' }, 92 | \ { 'color': 85, 'name': 'SeaGreen1', 'hex': '#5fffaf' }, 93 | \ { 'color': 86, 'name': 'Aquamarine1', 'hex': '#5fffd7' }, 94 | \ { 'color': 87, 'name': 'DarkSlateGray2', 'hex': '#5fffff' }, 95 | \ { 'color': 88, 'name': 'DarkRed', 'hex': '#870000' }, 96 | \ { 'color': 89, 'name': 'DeepPink4', 'hex': '#87005f' }, 97 | \ { 'color': 90, 'name': 'DarkMagenta', 'hex': '#870087' }, 98 | \ { 'color': 91, 'name': 'DarkMagenta', 'hex': '#8700af' }, 99 | \ { 'color': 92, 'name': 'DarkViolet', 'hex': '#8700d7' }, 100 | \ { 'color': 93, 'name': 'Purple', 'hex': '#8700ff' }, 101 | \ { 'color': 94, 'name': 'Orange4', 'hex': '#875f00' }, 102 | \ { 'color': 95, 'name': 'LightPink4', 'hex': '#875f5f' }, 103 | \ { 'color': 96, 'name': 'Plum4', 'hex': '#875f87' }, 104 | \ { 'color': 97, 'name': 'MediumPurple3', 'hex': '#875faf' }, 105 | \ { 'color': 98, 'name': 'MediumPurple3', 'hex': '#875fd7' }, 106 | \ { 'color': 99, 'name': 'SlateBlue1', 'hex': '#875fff' }, 107 | \ { 'color': 100, 'name': 'Yellow4', 'hex': '#878700' }, 108 | \ { 'color': 101, 'name': 'Wheat4', 'hex': '#87875f' }, 109 | \ { 'color': 102, 'name': 'Grey53', 'hex': '#878787' }, 110 | \ { 'color': 103, 'name': 'LightSlateGrey', 'hex': '#8787af' }, 111 | \ { 'color': 104, 'name': 'MediumPurple', 'hex': '#8787d7' }, 112 | \ { 'color': 105, 'name': 'LightSlateBlue', 'hex': '#8787ff' }, 113 | \ { 'color': 106, 'name': 'Yellow4', 'hex': '#87af00' }, 114 | \ { 'color': 107, 'name': 'DarkOliveGreen3', 'hex': '#87af5f' }, 115 | \ { 'color': 108, 'name': 'DarkSeaGreen', 'hex': '#87af87' }, 116 | \ { 'color': 109, 'name': 'LightSkyBlue3', 'hex': '#87afaf' }, 117 | \ { 'color': 110, 'name': 'LightSkyBlue3', 'hex': '#87afd7' }, 118 | \ { 'color': 111, 'name': 'SkyBlue2', 'hex': '#87afff' }, 119 | \ { 'color': 112, 'name': 'Chartreuse2', 'hex': '#87d700' }, 120 | \ { 'color': 113, 'name': 'DarkOliveGreen3', 'hex': '#87d75f' }, 121 | \ { 'color': 114, 'name': 'PaleGreen3', 'hex': '#87d787' }, 122 | \ { 'color': 115, 'name': 'DarkSeaGreen3', 'hex': '#87d7af' }, 123 | \ { 'color': 116, 'name': 'DarkSlateGray3', 'hex': '#87d7d7' }, 124 | \ { 'color': 117, 'name': 'SkyBlue1', 'hex': '#87d7ff' }, 125 | \ { 'color': 118, 'name': 'Chartreuse1', 'hex': '#87ff00' }, 126 | \ { 'color': 119, 'name': 'LightGreen', 'hex': '#87ff5f' }, 127 | \ { 'color': 120, 'name': 'LightGreen', 'hex': '#87ff87' }, 128 | \ { 'color': 121, 'name': 'PaleGreen1', 'hex': '#87ffaf' }, 129 | \ { 'color': 122, 'name': 'Aquamarine1', 'hex': '#87ffd7' }, 130 | \ { 'color': 123, 'name': 'DarkSlateGray1', 'hex': '#87ffff' }, 131 | \ { 'color': 124, 'name': 'Red3', 'hex': '#af0000' }, 132 | \ { 'color': 125, 'name': 'DeepPink4', 'hex': '#af005f' }, 133 | \ { 'color': 126, 'name': 'MediumVioletRed', 'hex': '#af0087' }, 134 | \ { 'color': 127, 'name': 'Magenta3', 'hex': '#af00af' }, 135 | \ { 'color': 128, 'name': 'DarkViolet', 'hex': '#af00d7' }, 136 | \ { 'color': 129, 'name': 'Purple', 'hex': '#af00ff' }, 137 | \ { 'color': 130, 'name': 'DarkOrange3', 'hex': '#af5f00' }, 138 | \ { 'color': 131, 'name': 'IndianRed', 'hex': '#af5f5f' }, 139 | \ { 'color': 132, 'name': 'HotPink3', 'hex': '#af5f87' }, 140 | \ { 'color': 133, 'name': 'MediumOrchid3', 'hex': '#af5faf' }, 141 | \ { 'color': 134, 'name': 'MediumOrchid', 'hex': '#af5fd7' }, 142 | \ { 'color': 135, 'name': 'MediumPurple2', 'hex': '#af5fff' }, 143 | \ { 'color': 136, 'name': 'DarkGoldenrod', 'hex': '#af8700' }, 144 | \ { 'color': 137, 'name': 'LightSalmon3', 'hex': '#af875f' }, 145 | \ { 'color': 138, 'name': 'RosyBrown', 'hex': '#af8787' }, 146 | \ { 'color': 139, 'name': 'Grey63', 'hex': '#af87af' }, 147 | \ { 'color': 140, 'name': 'MediumPurple2', 'hex': '#af87d7' }, 148 | \ { 'color': 141, 'name': 'MediumPurple1', 'hex': '#af87ff' }, 149 | \ { 'color': 142, 'name': 'Gold3', 'hex': '#afaf00' }, 150 | \ { 'color': 143, 'name': 'DarkKhaki', 'hex': '#afaf5f' }, 151 | \ { 'color': 144, 'name': 'NavajoWhite3', 'hex': '#afaf87' }, 152 | \ { 'color': 145, 'name': 'Grey69', 'hex': '#afafaf' }, 153 | \ { 'color': 146, 'name': 'LightSteelBlue3', 'hex': '#afafd7' }, 154 | \ { 'color': 147, 'name': 'LightSteelBlue', 'hex': '#afafff' }, 155 | \ { 'color': 148, 'name': 'Yellow3', 'hex': '#afd700' }, 156 | \ { 'color': 149, 'name': 'DarkOliveGreen3', 'hex': '#afd75f' }, 157 | \ { 'color': 150, 'name': 'DarkSeaGreen3', 'hex': '#afd787' }, 158 | \ { 'color': 151, 'name': 'DarkSeaGreen2', 'hex': '#afd7af' }, 159 | \ { 'color': 152, 'name': 'LightCyan3', 'hex': '#afd7d7' }, 160 | \ { 'color': 153, 'name': 'LightSkyBlue1', 'hex': '#afd7ff' }, 161 | \ { 'color': 154, 'name': 'GreenYellow', 'hex': '#afff00' }, 162 | \ { 'color': 155, 'name': 'DarkOliveGreen2', 'hex': '#afff5f' }, 163 | \ { 'color': 156, 'name': 'PaleGreen1', 'hex': '#afff87' }, 164 | \ { 'color': 157, 'name': 'DarkSeaGreen2', 'hex': '#afffaf' }, 165 | \ { 'color': 158, 'name': 'DarkSeaGreen1', 'hex': '#afffd7' }, 166 | \ { 'color': 159, 'name': 'PaleTurquoise1', 'hex': '#afffff' }, 167 | \ { 'color': 160, 'name': 'Red3', 'hex': '#d70000' }, 168 | \ { 'color': 161, 'name': 'DeepPink3', 'hex': '#d7005f' }, 169 | \ { 'color': 162, 'name': 'DeepPink3', 'hex': '#d70087' }, 170 | \ { 'color': 163, 'name': 'Magenta3', 'hex': '#d700af' }, 171 | \ { 'color': 164, 'name': 'Magenta3', 'hex': '#d700d7' }, 172 | \ { 'color': 165, 'name': 'Magenta2', 'hex': '#d700ff' }, 173 | \ { 'color': 166, 'name': 'DarkOrange3', 'hex': '#d75f00' }, 174 | \ { 'color': 167, 'name': 'IndianRed', 'hex': '#d75f5f' }, 175 | \ { 'color': 168, 'name': 'HotPink3', 'hex': '#d75f87' }, 176 | \ { 'color': 169, 'name': 'HotPink2', 'hex': '#d75faf' }, 177 | \ { 'color': 170, 'name': 'Orchid', 'hex': '#d75fd7' }, 178 | \ { 'color': 171, 'name': 'MediumOrchid1', 'hex': '#d75fff' }, 179 | \ { 'color': 172, 'name': 'Orange3', 'hex': '#d78700' }, 180 | \ { 'color': 173, 'name': 'LightSalmon3', 'hex': '#d7875f' }, 181 | \ { 'color': 174, 'name': 'LightPink3', 'hex': '#d78787' }, 182 | \ { 'color': 175, 'name': 'Pink3', 'hex': '#d787af' }, 183 | \ { 'color': 176, 'name': 'Plum3', 'hex': '#d787d7' }, 184 | \ { 'color': 177, 'name': 'Violet', 'hex': '#d787ff' }, 185 | \ { 'color': 178, 'name': 'Gold3', 'hex': '#d7af00' }, 186 | \ { 'color': 179, 'name': 'LightGoldenrod3', 'hex': '#d7af5f' }, 187 | \ { 'color': 180, 'name': 'Tan', 'hex': '#d7af87' }, 188 | \ { 'color': 181, 'name': 'MistyRose3', 'hex': '#d7afaf' }, 189 | \ { 'color': 182, 'name': 'Thistle3', 'hex': '#d7afd7' }, 190 | \ { 'color': 183, 'name': 'Plum2', 'hex': '#d7afff' }, 191 | \ { 'color': 184, 'name': 'Yellow3', 'hex': '#d7d700' }, 192 | \ { 'color': 185, 'name': 'Khaki3', 'hex': '#d7d75f' }, 193 | \ { 'color': 186, 'name': 'LightGoldenrod2', 'hex': '#d7d787' }, 194 | \ { 'color': 187, 'name': 'LightYellow3', 'hex': '#d7d7af' }, 195 | \ { 'color': 188, 'name': 'Grey84', 'hex': '#d7d7d7' }, 196 | \ { 'color': 189, 'name': 'LightSteelBlue1', 'hex': '#d7d7ff' }, 197 | \ { 'color': 190, 'name': 'Yellow2', 'hex': '#d7ff00' }, 198 | \ { 'color': 191, 'name': 'DarkOliveGreen1', 'hex': '#d7ff5f' }, 199 | \ { 'color': 192, 'name': 'DarkOliveGreen1', 'hex': '#d7ff87' }, 200 | \ { 'color': 193, 'name': 'DarkSeaGreen1', 'hex': '#d7ffaf' }, 201 | \ { 'color': 194, 'name': 'Honeydew2', 'hex': '#d7ffd7' }, 202 | \ { 'color': 195, 'name': 'LightCyan1', 'hex': '#d7ffff' }, 203 | \ { 'color': 196, 'name': 'Red1', 'hex': '#ff0000' }, 204 | \ { 'color': 197, 'name': 'DeepPink2', 'hex': '#ff005f' }, 205 | \ { 'color': 198, 'name': 'DeepPink1', 'hex': '#ff0087' }, 206 | \ { 'color': 199, 'name': 'DeepPink1', 'hex': '#ff00af' }, 207 | \ { 'color': 200, 'name': 'Magenta2', 'hex': '#ff00d7' }, 208 | \ { 'color': 201, 'name': 'Magenta1', 'hex': '#ff00ff' }, 209 | \ { 'color': 202, 'name': 'OrangeRed1', 'hex': '#ff5f00' }, 210 | \ { 'color': 203, 'name': 'IndianRed1', 'hex': '#ff5f5f' }, 211 | \ { 'color': 204, 'name': 'IndianRed1', 'hex': '#ff5f87' }, 212 | \ { 'color': 205, 'name': 'HotPink', 'hex': '#ff5faf' }, 213 | \ { 'color': 206, 'name': 'HotPink', 'hex': '#ff5fd7' }, 214 | \ { 'color': 207, 'name': 'MediumOrchid1', 'hex': '#ff5fff' }, 215 | \ { 'color': 208, 'name': 'DarkOrange', 'hex': '#ff8700' }, 216 | \ { 'color': 209, 'name': 'Salmon1', 'hex': '#ff875f' }, 217 | \ { 'color': 210, 'name': 'LightCoral', 'hex': '#ff8787' }, 218 | \ { 'color': 211, 'name': 'PaleVioletRed1', 'hex': '#ff87af' }, 219 | \ { 'color': 212, 'name': 'Orchid2', 'hex': '#ff87d7' }, 220 | \ { 'color': 213, 'name': 'Orchid1', 'hex': '#ff87ff' }, 221 | \ { 'color': 214, 'name': 'Orange1', 'hex': '#ffaf00' }, 222 | \ { 'color': 215, 'name': 'SandyBrown', 'hex': '#ffaf5f' }, 223 | \ { 'color': 216, 'name': 'LightSalmon1', 'hex': '#ffaf87' }, 224 | \ { 'color': 217, 'name': 'LightPink1', 'hex': '#ffafaf' }, 225 | \ { 'color': 218, 'name': 'Pink1', 'hex': '#ffafd7' }, 226 | \ { 'color': 219, 'name': 'Plum1', 'hex': '#ffafff' }, 227 | \ { 'color': 220, 'name': 'Gold1', 'hex': '#ffd700' }, 228 | \ { 'color': 221, 'name': 'LightGoldenrod2', 'hex': '#ffd75f' }, 229 | \ { 'color': 222, 'name': 'LightGoldenrod2', 'hex': '#ffd787' }, 230 | \ { 'color': 223, 'name': 'NavajoWhite1', 'hex': '#ffd7af' }, 231 | \ { 'color': 224, 'name': 'MistyRose1', 'hex': '#ffd7d7' }, 232 | \ { 'color': 225, 'name': 'Thistle1', 'hex': '#ffd7ff' }, 233 | \ { 'color': 226, 'name': 'Yellow1', 'hex': '#ffff00' }, 234 | \ { 'color': 227, 'name': 'LightGoldenrod1', 'hex': '#ffff5f' }, 235 | \ { 'color': 228, 'name': 'Khaki1', 'hex': '#ffff87' }, 236 | \ { 'color': 229, 'name': 'Wheat1', 'hex': '#ffffaf' }, 237 | \ { 'color': 230, 'name': 'Cornsilk1', 'hex': '#ffffd7' }, 238 | \ { 'color': 231, 'name': 'Grey100', 'hex': '#ffffff' }, 239 | \ { 'color': 232, 'name': 'Grey3', 'hex': '#080808' }, 240 | \ { 'color': 233, 'name': 'Grey7', 'hex': '#121212' }, 241 | \ { 'color': 234, 'name': 'Grey11', 'hex': '#1c1c1c' }, 242 | \ { 'color': 235, 'name': 'Grey15', 'hex': '#262626' }, 243 | \ { 'color': 236, 'name': 'Grey19', 'hex': '#303030' }, 244 | \ { 'color': 237, 'name': 'Grey23', 'hex': '#3a3a3a' }, 245 | \ { 'color': 238, 'name': 'Grey27', 'hex': '#444444' }, 246 | \ { 'color': 239, 'name': 'Grey30', 'hex': '#4e4e4e' }, 247 | \ { 'color': 240, 'name': 'Grey35', 'hex': '#585858' }, 248 | \ { 'color': 241, 'name': 'Grey39', 'hex': '#626262' }, 249 | \ { 'color': 242, 'name': 'Grey42', 'hex': '#6c6c6c' }, 250 | \ { 'color': 243, 'name': 'Grey46', 'hex': '#767676' }, 251 | \ { 'color': 244, 'name': 'Grey50', 'hex': '#808080' }, 252 | \ { 'color': 245, 'name': 'Grey54', 'hex': '#8a8a8a' }, 253 | \ { 'color': 246, 'name': 'Grey58', 'hex': '#949494' }, 254 | \ { 'color': 247, 'name': 'Grey62', 'hex': '#9e9e9e' }, 255 | \ { 'color': 248, 'name': 'Grey66', 'hex': '#a8a8a8' }, 256 | \ { 'color': 249, 'name': 'Grey70', 'hex': '#b2b2b2' }, 257 | \ { 'color': 250, 'name': 'Grey74', 'hex': '#bcbcbc' }, 258 | \ { 'color': 251, 'name': 'Grey78', 'hex': '#c6c6c6' }, 259 | \ { 'color': 252, 'name': 'Grey82', 'hex': '#d0d0d0' }, 260 | \ { 'color': 253, 'name': 'Grey85', 'hex': '#dadada' }, 261 | \ { 'color': 254, 'name': 'Grey89', 'hex': '#e4e4e4' }, 262 | \ { 'color': 255, 'name': 'Grey93', 'hex': '#eeeeee' }, 263 | \ ] 264 | 265 | 266 | #---------------------------------------------------------------------- 267 | # initialize 268 | #---------------------------------------------------------------------- 269 | var _palette: list> 270 | var cnames = {} 271 | 272 | for color in color_definition 273 | final cc: number = str2nr(strpart(color.hex, 1), 16) 274 | final r: number = and(cc / 0x10000, 0xff) 275 | final g: number = and(cc / 0x100, 0xff) 276 | final b: number = and(cc, 0xff) 277 | final p: list = [r, g, b] 278 | _palette += [p] 279 | cnames[tolower(color.name)] = color.color 280 | endfor 281 | 282 | final palette: list> = deepcopy(_palette) 283 | var _diff_lookup: list = repeat([0], 512 * 3) 284 | 285 | for i in range(256) 286 | final k: number = i * i 287 | final dr: number = k * 30 * 30 288 | final dg: number = k * 59 * 59 289 | final db: number = k * 11 * 11 290 | _diff_lookup[ 256 + i] = dr 291 | _diff_lookup[ 256 - i] = dr 292 | _diff_lookup[ 768 + i] = dg 293 | _diff_lookup[ 768 - i] = dg 294 | _diff_lookup[1280 + i] = db 295 | _diff_lookup[1280 - i] = db 296 | endfor 297 | 298 | final diff_lookup: list = deepcopy(_diff_lookup) 299 | 300 | 301 | #---------------------------------------------------------------------- 302 | # bestfit color 303 | #---------------------------------------------------------------------- 304 | export def BestfitColor(r: number, g: number, b: number, limit: number = 256): number 305 | final R: number = (r < 256) ? r : 255 306 | final G: number = (g < 256) ? g : 255 307 | final B: number = (b < 256) ? b : 255 308 | final LIMIT: number = (limit < 256) ? limit : 256 309 | final lookup: list = diff_lookup 310 | var lowest = 0x7fffffff 311 | var bestfit = 0 312 | var index = 0 313 | while index < LIMIT 314 | final rgb: list = palette[index] 315 | var diff = lookup[768 + rgb[1] - G] 316 | if diff < lowest 317 | diff += lookup[256 + rgb[0] - R] 318 | if diff < lowest 319 | diff += lookup[1280 + rgb[2] - B] 320 | if diff < lowest 321 | lowest = diff 322 | bestfit = index 323 | endif 324 | if diff <= 0 325 | break 326 | endif 327 | endif 328 | endif 329 | index += 1 330 | endwhile 331 | return bestfit 332 | enddef 333 | 334 | 335 | #---------------------------------------------------------------------- 336 | # for 8 colors 337 | #---------------------------------------------------------------------- 338 | export def Bestfit8(r: number, g: number, b: number): number 339 | return BestfitColor(r, g, b, 8) 340 | enddef 341 | 342 | 343 | #---------------------------------------------------------------------- 344 | # for 16 colors 345 | #---------------------------------------------------------------------- 346 | export def Bestfit16(r: number, g: number, b: number): number 347 | return BestfitColor(r, g, b, 16) 348 | enddef 349 | 350 | #---------------------------------------------------------------------- 351 | # for 256 colors 352 | #---------------------------------------------------------------------- 353 | export def Bestfit256(r: number, g: number, b: number): number 354 | return BestfitColor(r, g, b, 256) 355 | enddef 356 | 357 | 358 | #---------------------------------------------------------------------- 359 | # for 256 colors 360 | #---------------------------------------------------------------------- 361 | var matched = {} 362 | 363 | export def Match(r: number, g: number, b: number, num: number = -1): number 364 | final rr = (r < 256) ? r : 255 365 | final gg = (g < 256) ? g : 255 366 | final bb = (b < 256) ? b : 255 367 | final key: number = (rr * 4096 / 4) + (gg * 64 / 4) + (bb / 4) 368 | if !has_key(matched, key) 369 | var N: number = 256 370 | if num >= 0 371 | N = num 372 | else 373 | if exists('g:quickui#palette#number') 374 | N = g:quickui#palette#number 375 | endif 376 | endif 377 | final cc: number = BestfitColor(rr, gg, bb, N) 378 | matched[key] = cc 379 | endif 380 | return matched[key] 381 | enddef 382 | 383 | 384 | #---------------------------------------------------------------------- 385 | # convert #112233 to [0x11, 0x22, 0x33] 386 | #---------------------------------------------------------------------- 387 | export def Hex2RGB(hex: string): list 388 | var head: string = strpart(hex, 0, 1) 389 | var r: number = 0 390 | var g: number = 0 391 | var b: number = 0 392 | if head == '#' 393 | final c: number = str2nr(strpart(hex, 1), 16) 394 | r = and(c / 0x10000, 0xff) 395 | g = and(c / 0x100, 0xff) 396 | b = and(c, 0xff) 397 | elseif head == '(' 398 | head = strpart(hex, 1, len(hex) - 2) 399 | final part: list = split(head, ',') 400 | r = str2nr(part[0]) 401 | g = str2nr(part[1]) 402 | b = str2nr(part[2]) 403 | endif 404 | return [r, g, b] 405 | enddef 406 | 407 | 408 | #---------------------------------------------------------------------- 409 | # hex to palette index 410 | #---------------------------------------------------------------------- 411 | export def Hex2Index(hex: string, num: number = -1): number 412 | final cc: list = Hex2RGB(hex) 413 | return Match(cc[0], cc[1], cc[2], num) 414 | enddef 415 | 416 | 417 | #---------------------------------------------------------------------- 418 | # search name 419 | #---------------------------------------------------------------------- 420 | export def Name2Index(name: string, default: number = 0): number 421 | final head = strpart(name, 0, 1) 422 | if head == '#' || head == '(' 423 | return Hex2Index(name) 424 | else 425 | final nm = tolower(name) 426 | if exists('v:colornames') 427 | if has_key(v:colornames, nm) 428 | final hex = v:colornames[nm] 429 | return Hex2Index(hex) 430 | endif 431 | endif 432 | return get(cnames, tolower(name), default) 433 | endif 434 | enddef 435 | 436 | 437 | #---------------------------------------------------------------------- 438 | # benchmark 439 | #---------------------------------------------------------------------- 440 | export def Timing(): string 441 | var ts = reltime() 442 | for i in range(256) 443 | Match(i, i, i) 444 | endfor 445 | var tt = reltime(ts) 446 | return reltimestr(tt) 447 | enddef 448 | 449 | 450 | -------------------------------------------------------------------------------- /autoload/quickui/preview.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " preview.vim - 4 | " 5 | " Created by skywind on 2020/01/11 6 | " Last Modified: 2021/12/13 22:32 7 | " 8 | "====================================================================== 9 | 10 | " vim: set noet fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : 11 | 12 | 13 | "---------------------------------------------------------------------- 14 | " private object 15 | "---------------------------------------------------------------------- 16 | let s:private = {'winid': -1, 'background': -1, 'state':0} 17 | 18 | 19 | "---------------------------------------------------------------------- 20 | " position to a proper location 21 | "---------------------------------------------------------------------- 22 | function! s:around_cursor(width, height) 23 | let cursor_pos = quickui#core#cursor_pos() 24 | let row = cursor_pos[0] - a:height 25 | let col = cursor_pos[1] + 1 26 | if quickui#core#in_screen(row, col, a:width, a:height) 27 | return [row, col] 28 | endif 29 | if col + a:width - 1 > &columns 30 | let col = col - (1 + a:width) 31 | if quickui#core#in_screen(row, col, a:width, a:height) 32 | return [row, col] 33 | endif 34 | endif 35 | if row < 1 36 | let row = row + (1 + a:height) 37 | if quickui#core#in_screen(row, col, a:width, a:height) 38 | return [row, col] 39 | endif 40 | endif 41 | if cursor_pos[0] - a:height - 2 < 1 42 | let row = cursor_pos[0] + 1 43 | else 44 | let row = cursor_pos[0] - a:height 45 | endif 46 | if cursor_pos[1] + a:width + 2 < &columns 47 | let col = cursor_pos[1] + 1 48 | else 49 | let col = cursor_pos[1] - a:width 50 | endif 51 | return quickui#core#screen_fit(row, col, a:width, a:height) 52 | endfunc 53 | 54 | 55 | "---------------------------------------------------------------------- 56 | " create preview window 57 | "---------------------------------------------------------------------- 58 | function! quickui#preview#display(content, opts) 59 | call quickui#preview#close() 60 | if type(a:content) == v:t_string && filereadable(a:content) == 0 61 | call quickui#utils#errmsg('E212: Can not open file: '. a:content) 62 | return -1 63 | endif 64 | let s:private.state = 0 65 | if type(a:content) == v:t_string 66 | silent let source = bufadd(a:content) 67 | silent call bufload(source) 68 | elseif type(a:content) == v:t_list 69 | let source = a:content 70 | endif 71 | let winid = -1 72 | let title = '' 73 | if has_key(a:opts, 'title') && (a:opts.title != '') 74 | let title = ' ' . a:opts.title .' ' 75 | endif 76 | let w = get(a:opts, 'w', -1) 77 | let h = get(a:opts, 'h', -1) 78 | let w = (w < 0)? 50 : w 79 | let h = (h < 0)? 10 : h 80 | let border = get(a:opts, 'border', g:quickui#style#border) 81 | let button = (get(a:opts, 'close', '') == 'button')? 1 : 0 82 | let color = get(a:opts, 'color', 'QuickPreview') 83 | let p = s:around_cursor(w + (border? 2 : 0), h + (border? 2 : 0)) 84 | if has_key(a:opts, 'col') 85 | let p[0] = get(a:opts, 'line', get(a:opts, 'row', 1)) 86 | let p[1] = get(a:opts, 'col', 1) 87 | endif 88 | if has('nvim') == 0 89 | let winid = popup_create(source, {'wrap':1, 'mapping':0, 'hidden':1}) 90 | let opts = {'maxwidth':w, 'maxheight':h, 'minwidth':w, 'minheight':h} 91 | call popup_move(winid, opts) 92 | let opts = {'close':'button'} 93 | let opts.border = border? [1,1,1,1,1,1,1,1,1] : repeat([0], 9) 94 | let opts.resize = 0 95 | let opts.highlight = color 96 | let opts.borderchars = quickui#core#border_vim(border) 97 | if get(a:opts, 'persist', 0) == 0 98 | let opts.moved = 'any' 99 | endif 100 | let opts.drag = 1 101 | let opts.line = p[0] 102 | let opts.col = p[1] 103 | if title != '' 104 | let opts.title = title 105 | endif 106 | let opts.callback = function('s:popup_exit') 107 | " let opts.fixed = 'true' 108 | if has_key(a:opts, 'bordercolor') 109 | let c = a:opts.bordercolor 110 | let opts.borderhighlight = [c, c, c, c] 111 | endif 112 | call popup_setoptions(winid, opts) 113 | let s:private.winid = winid 114 | call popup_show(winid) 115 | else 116 | let opts = {'focusable':0, 'style':'minimal', 'relative':'editor'} 117 | let opts.width = w 118 | let opts.height = h 119 | let opts.row = p[0] 120 | let opts.col = p[1] 121 | if has_key(a:opts, 'focusable') 122 | let opts.focusable = a:opts.focusable 123 | endif 124 | if type(source) == v:t_number 125 | let bid = source 126 | else 127 | let bid = quickui#core#scratch_buffer('preview', source) 128 | endif 129 | if has('nvim-0.6.0') 130 | let opts.noautocmd = 1 131 | endif 132 | let winid = nvim_open_win(bid, 0, opts) 133 | let s:private.winid = winid 134 | let high = 'Normal:'.color.',NonText:'.color.',EndOfBuffer:'.color 135 | call nvim_win_set_option(winid, 'winhl', high) 136 | let s:private.background = -1 137 | if border > 0 && get(g:, 'quickui_nvim_simulate_border', 1) != 0 138 | let back = quickui#utils#make_border(w, h, border, title, button) 139 | let nbid = quickui#core#scratch_buffer('previewborder', back) 140 | let op = {'relative':'editor', 'focusable':0, 'style':'minimal'} 141 | let op.width = w + 2 142 | let op.height = h + 2 143 | let pos = nvim_win_get_config(winid) 144 | let op.row = pos.row - 1 145 | let op.col = pos.col - 1 146 | let bordercolor = get(a:opts, 'bordercolor', color) 147 | if has('nvim-0.6.0') 148 | let op.noautocmd = 1 149 | endif 150 | let background = nvim_open_win(nbid, 0, op) 151 | call nvim_win_set_option(background, 'winhl', 'Normal:'. bordercolor) 152 | let s:private.background = background 153 | endif 154 | endif 155 | let cmdlist = ['setlocal signcolumn=no norelativenumber'] 156 | if get(a:opts, 'number', 1) == 0 157 | let cmdlist += ['setlocal nonumber'] 158 | else 159 | let cmdlist += ['setlocal number'] 160 | endif 161 | let cursor = get(a:opts, 'cursor', -1) 162 | if cursor > 0 163 | let cmdlist += ['exec "normal! gg' . cursor . 'Gzz"'] 164 | endif 165 | if has_key(a:opts, 'syntax') 166 | let cmdlist += ['setl ft=' . fnameescape(a:opts.syntax) ] 167 | endif 168 | let cmdlist += ['silent! setlocal scrolloff=0'] 169 | call setbufvar(winbufnr(winid), '__quickui_cursor__', cursor) 170 | call quickui#core#win_execute(winid, cmdlist) 171 | call quickui#utils#update_cursor(winid) 172 | let s:private.state = 1 173 | if has('nvim') 174 | if get(a:opts, 'persist', 0) == 0 175 | autocmd CursorMoved ++once call s:autoclose_preview_window() 176 | endif 177 | endif 178 | return winid 179 | endfunc 180 | 181 | 182 | "---------------------------------------------------------------------- 183 | " exit callback 184 | "---------------------------------------------------------------------- 185 | function! s:popup_exit(winid, code) 186 | let s:private.winid = -1 187 | let s:private.state = 0 188 | endfunc 189 | 190 | 191 | "---------------------------------------------------------------------- 192 | " close window 193 | "---------------------------------------------------------------------- 194 | function! quickui#preview#close() 195 | if s:private.winid >= 0 196 | if has('nvim') == 0 197 | call popup_close(s:private.winid, 0) 198 | let s:private.winid = -1 199 | else 200 | call nvim_win_close(s:private.winid, 0) 201 | let s:private.winid = -1 202 | if s:private.background >= 0 203 | call nvim_win_close(s:private.background, 0) 204 | let s:private.background = -1 205 | endif 206 | endif 207 | endif 208 | let s:private.state = 0 209 | endfunc 210 | 211 | 212 | "---------------------------------------------------------------------- 213 | " return state 214 | "---------------------------------------------------------------------- 215 | function! quickui#preview#visible() 216 | return s:private.state 217 | endfunc 218 | 219 | 220 | "---------------------------------------------------------------------- 221 | " quit 222 | "---------------------------------------------------------------------- 223 | function! s:autoclose_preview_window() 224 | if s:private.state != 0 225 | if s:private.winid >= 0 226 | call quickui#preview#close() 227 | endif 228 | endif 229 | endfunc 230 | 231 | 232 | "---------------------------------------------------------------------- 233 | " scroll preview window 234 | "---------------------------------------------------------------------- 235 | function! quickui#preview#scroll(offset) 236 | if s:private.state != 0 237 | let winid = s:private.winid 238 | if s:private.winid >= 0 239 | noautocmd call quickui#utils#scroll(winid, a:offset) 240 | noautocmd call quickui#utils#update_cursor(winid) 241 | endif 242 | endif 243 | endfunc 244 | 245 | 246 | "---------------------------------------------------------------------- 247 | " press esc to close 248 | "---------------------------------------------------------------------- 249 | function! s:press_esc() 250 | exec "nunmap " 251 | call quickui#preview#close() 252 | endfunc 253 | 254 | 255 | "---------------------------------------------------------------------- 256 | " preview file 257 | "---------------------------------------------------------------------- 258 | function! quickui#preview#open(content, opts) 259 | call quickui#preview#close() 260 | if type(a:content) == v:t_string && filereadable(a:content) == 0 261 | call quickui#utils#errmsg('E484: Cannot open file ' . a:content) 262 | return -1 263 | endif 264 | let opts = {} 265 | let opts.w = get(g:, 'quickui_preview_w', g:quickui#style#preview_w) 266 | let opts.h = get(g:, 'quickui_preview_h', g:quickui#style#preview_h) 267 | let opts.number = get(a:opts, 'number', g:quickui#style#preview_number) 268 | let opts.cursor = get(a:opts, 'cursor', -1) 269 | let title = has_key(a:opts, 'title')? (' ' .. a:opts.title) : '' 270 | if type(a:content) == v:t_string 271 | let name = fnamemodify(a:content, ':p:t') 272 | let opts.title = 'Preview: ' . name . title 273 | else 274 | let opts.title = 'Preview' .. ((title == '')? '' : (':' .. title)) 275 | endif 276 | if g:quickui#style#preview_bordercolor != '' 277 | let opts.bordercolor = g:quickui#style#preview_bordercolor 278 | endif 279 | let opts.persist = get(a:opts, 'persist', 0) 280 | let opts.focusable = get(g:, 'quickui_preview_focusable', 1) 281 | if has_key(a:opts, 'syntax') 282 | let opts.syntax = a:opts.syntax 283 | endif 284 | if has_key(a:opts, 'col') 285 | let opts.col = a:opts.col 286 | let opts.line = get(a:opts, 'line', get(a:opts, 'row')) 287 | endif 288 | if has_key(a:opts, 'w') 289 | let opts.w = a:opts.w 290 | let opts.h = get(a:opts, 'h', opts.h) 291 | endif 292 | let hr = quickui#preview#display(a:content, opts) 293 | exec "nnoremap :call press_esc()" 294 | return hr 295 | endfunc 296 | 297 | 298 | 299 | 300 | -------------------------------------------------------------------------------- /autoload/quickui/style.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " style.vim - 4 | " 5 | " Created by skywind on 2019/12/19 6 | " Last Modified: 2019/12/19 16:06:59 7 | " 8 | "====================================================================== 9 | 10 | "---------------------------------------------------------------------- 11 | " default border style: 1/ascii, 2/single, 3/double 12 | "---------------------------------------------------------------------- 13 | let g:quickui#style#border = get(g:, 'quickui#style#border', 1) 14 | 15 | let g:quickui#style#tip_head = '[tip]' 16 | 17 | let g:quickui#style#preview_w = 85 18 | let g:quickui#style#preview_h = 10 19 | let g:quickui#style#preview_number = 1 20 | let g:quickui#style#preview_bordercolor = '' 21 | 22 | 23 | -------------------------------------------------------------------------------- /autoload/quickui/tags.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " tags.vim - 4 | " 5 | " Created by skywind on 2020/01/07 6 | " Last Modified: 2024/03/23 21:14 7 | " 8 | "====================================================================== 9 | 10 | " vim: set noet fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : 11 | 12 | "---------------------------------------------------------------------- 13 | " wrapping of vim's taglist() 14 | "---------------------------------------------------------------------- 15 | function! quickui#tags#taglist(pattern) 16 | let ftags = [] 17 | try 18 | let ftags = taglist(a:pattern) 19 | catch /^Vim\%((\a\+)\)\=:E/ 20 | " if error occured, reset tagbsearch option and try again. 21 | let bak = &tagbsearch 22 | set notagbsearch 23 | let ftags = taglist(a:pattern) 24 | let &tagbsearch = bak 25 | endtry 26 | " take care ctags windows filename bug 27 | let win = has('win32') || has('win64') || has('win95') || has('win16') 28 | for item in ftags 29 | let name = get(item, 'filename', '') 30 | let item.baditem = 0 31 | if win != 0 32 | if stridx(name, '\\') >= 0 33 | let part = split(name, '\\', 1) 34 | let elem = [] 35 | for n in part 36 | if n != '' 37 | let elem += [n] 38 | endif 39 | endfor 40 | let name = join(elem, '\') 41 | let item.filename = name 42 | if has_key(item, 'line') == 0 43 | if has_key(item, 'signature') == 0 44 | let kind = get(item, 'kind', '') 45 | if kind != 'p' && kind != 'f' 46 | let item.baditem = 1 47 | endif 48 | endif 49 | endif 50 | end 51 | endif 52 | endfor 53 | return ftags 54 | endfunc 55 | 56 | 57 | "---------------------------------------------------------------------- 58 | " easy tagname 59 | "---------------------------------------------------------------------- 60 | function! quickui#tags#tagfind(tagname) 61 | let pattern = escape(a:tagname, '[\*~^') 62 | let result = quickui#tags#taglist("^". pattern . "$") 63 | if type(result) == 0 || (type(result) == 3 && result == []) 64 | if pattern !~ '^\(catch\|if\|for\|while\|switch\)$' 65 | let result = quickui#tags#taglist('::'. pattern .'$') 66 | endif 67 | endif 68 | if type(result) == 0 || (type(result) == 3 && result == []) 69 | return [] 70 | endif 71 | let final = [] 72 | let check = {} 73 | for item in result 74 | if item.baditem != 0 75 | continue 76 | endif 77 | " remove duplicated tags 78 | let signature = get(item, 'name', '') . ':' 79 | let signature .= get(item, 'cmd', '') . ':' 80 | let signature .= get(item, 'kind', '') . ':' 81 | let signature .= get(item, 'line', '') . ':' 82 | let signature .= get(item, 'filename', '') 83 | if !has_key(check, signature) 84 | let final += [item] 85 | let check[signature] = 1 86 | endif 87 | endfor 88 | return final 89 | endfunc 90 | 91 | 92 | "---------------------------------------------------------------------- 93 | " function signature 94 | "---------------------------------------------------------------------- 95 | function! quickui#tags#signature(funname, fn_only, filetype) 96 | let tags = quickui#tags#tagfind(a:funname) 97 | let funpat = escape(a:funname, '[\*~^') 98 | let fill_tag = [] 99 | let ft = (a:filetype == '')? &filetype : a:filetype 100 | for i in tags 101 | if !has_key(i, 'name') 102 | continue 103 | endif 104 | if has_key(i, 'language') 105 | endif 106 | if has_key(i, 'filename') && ft != '*' 107 | let ename = tolower(fnamemodify(i.filename, ':e')) 108 | let c = ['c', 'cpp', 'cc', 'cxx', 'h', 'hpp', 'hh', 'm', 'mm'] 109 | if index(['c', 'cpp', 'objc', 'objcpp'], ft) >= 0 110 | if index(c, ename) < 0 111 | continue 112 | endif 113 | elseif ft == 'python' 114 | if index(['py', 'pyw'], ename) < 0 115 | continue 116 | endif 117 | elseif ft == 'java' && ename != 'java' 118 | continue 119 | elseif ft == 'ruby' && ename != 'rb' 120 | continue 121 | elseif ft == 'vim' && ename != 'vim' 122 | continue 123 | elseif ft == 'cs' && ename != 'cs' 124 | continue 125 | elseif ft == 'php' 126 | if index(['php', 'php4', 'php5', 'php6'], ename) < 0 127 | continue 128 | endif 129 | elseif ft == 'javascript' 130 | if index(['html', 'js', 'html5', 'xhtml', 'php'], ename) < 0 131 | continue 132 | endif 133 | endif 134 | endif 135 | if has_key(i, 'kind') 136 | " p: prototype/procedure; f: function; m: member 137 | if (a:fn_only == 0 || (i.kind == 'p' || i.kind == 'f') || 138 | \ (i.kind == 'm' && has_key(i, 'cmd') && 139 | \ match(i.cmd, '(') != -1)) && 140 | \ i.name =~ funpat 141 | if ft != 'cpp' || !has_key(i, 'class') || 142 | \ i.name !~ '::' || i.name =~ i.class 143 | let fill_tag += [i] 144 | endif 145 | endif 146 | else 147 | if a:fn_only == 0 && i.name == a:funname 148 | let fill_tag += [i] 149 | endif 150 | endif 151 | endfor 152 | let res = [] 153 | let check = {} 154 | for i in fill_tag 155 | if has_key(i, 'kind') && has_key(i, 'signature') 156 | if i.cmd[:1] == '/^' && i.cmd[-2:] == '$/' 157 | let tmppat = substitute(escape(i.name,'[\*~^'), 158 | \ '^.*::','','') 159 | if ft == 'cpp' 160 | let tmppat = substitute(tmppat,'\.*' 166 | endif 167 | let name = substitute(i.cmd[2:-3],tmppat,'',''). 168 | \ i.name . i.signature 169 | if i.kind == 'm' 170 | if has_key(i, 'class') 171 | let name = name . ' <-- class ' . i.class 172 | elseif has_key(i, 'struct') 173 | let name = name . ' <-- struct ' . i.struct 174 | elseif has_key(i, 'union') 175 | let name = name . ' <-- union ' . i.union 176 | endif 177 | endif 178 | else 179 | let name = i.name . i.signature 180 | if has_key(i, 'kind') && match('fm', i.kind) >= 0 181 | let sep = (ft == 'cpp' || ft == 'c')? '::' : '.' 182 | if has_key(i, 'class') 183 | let name = i.class . sep . name 184 | elseif has_key(i, 'struct') 185 | let name = i.struct . sep. name 186 | elseif has_key(i, 'union') 187 | let name = i.struct . sep. name 188 | endif 189 | endif 190 | endif 191 | elseif has_key(i, 'kind') 192 | if i.kind == 'd' 193 | let name = 'macro '. i.name 194 | elseif i.kind == 'c' 195 | let name = ((ft == 'vim')? 'command ' : 'class '). i.name 196 | elseif i.kind == 's' 197 | let name = 'struct '. i.name 198 | elseif i.kind == 'u' 199 | let name = 'union '. i.name 200 | elseif (match('fpmvt', i.kind) != -1) && 201 | \(has_key(i, 'cmd') && i.cmd[0] == '/') 202 | let tmppat = '\(\<'.i.name.'\>.\{-}\)' 203 | if index(['c', 'cpp', 'cs', 'java', 'javascript'], ft) >= 0 204 | " let tmppat = tmppat . ';.*' 205 | elseif ft == 'python' && (i.kind == 'm' || i.kind == 'f') 206 | let tmppat = tmppat . ':.*' 207 | elseif ft == 'tcl' && (i.kind == 'm' || i.kind == 'p') 208 | let tmppat = tmppat . '\({\)\?$' 209 | endif 210 | if i.kind == 'm' && &filetype == 'cpp' 211 | let tmppat=substitute(tmppat,'^\(.*::\)','\\(\1\\)\\?','') 212 | endif 213 | if match(i.cmd[2:-3], tmppat) != -1 214 | let name=substitute(i.cmd[2:-3], tmppat, '\1', '') 215 | if i.kind == 't' && name !~ '^\s*typedef\>' 216 | let name = 'typedef ' . i.name 217 | endif 218 | elseif i.kind == 't' 219 | let name = 'typedef ' . i.name 220 | elseif i.kind == 'v' 221 | let name = 'var ' . i.name 222 | else 223 | let name = i.name 224 | endif 225 | if i.kind == 'm' 226 | if has_key(i, 'class') 227 | let name = name . ' <-- class ' . i.class 228 | elseif has_key(i, 'struct') 229 | let name = name . ' <-- struct ' . i.struct 230 | elseif has_key(i, 'union') 231 | let name = name . ' <-- union ' . i.union 232 | endif 233 | endif 234 | let name = substitute(name, '^\s*\(.\{-}\)\s*$', '\1', '') 235 | if name[-1:] == ';' 236 | let name = name[0:-2] 237 | endif 238 | else 239 | let name = i.name 240 | endif 241 | else 242 | let name = i.name 243 | endif 244 | let name = substitute(name, '^\s\+', '', '') 245 | let name = substitute(name, '\s\+$', '', '') 246 | let name = substitute(name, '\s\+', ' ', 'g') 247 | let i.func_prototype = name 248 | let file_line = '' 249 | if has_key(i, 'filename') 250 | let file_line = fnamemodify(i.filename, ':t') 251 | if has_key(i, 'line') 252 | let file_line .= ':'. i.line 253 | elseif i.cmd > 0 254 | let file_line .= ':'. i.cmd 255 | if i.cmd =~ '^\s*\d\+\s*$' 256 | let i.line = str2nr(i.cmd) 257 | endif 258 | endif 259 | endif 260 | let i.file_line = file_line 261 | let res += [i] 262 | endfor 263 | let index = 1 264 | for i in res 265 | let name = i.func_prototype 266 | let file_line = i.file_line 267 | let desc = name. ' ('.index.'/'.len(res).') '.file_line 268 | let i.func_desc = desc 269 | let index += 1 270 | endfor 271 | return res 272 | endfunc 273 | 274 | 275 | "---------------------------------------------------------------------- 276 | " get function list 277 | "---------------------------------------------------------------------- 278 | function! quickui#tags#ctags_function(bid, ft) 279 | let parameters = { 280 | \ "aspvbs": "--asp-kinds=f", 281 | \ "awk": "--awk-kinds=f", 282 | \ "c": "--c-kinds=fp --language-force=C", 283 | \ "cpp": "--c++-kinds=fp --language-force=C++", 284 | \ "cs": "--c#-kinds=m", 285 | \ "erlang": "--erlang-kinds=f", 286 | \ "fortran": "--fortran-kinds=f", 287 | \ "java": "--java-kinds=m", 288 | \ "javascript": "--javascript-kinds=f", 289 | \ "lisp": "--lisp-kinds=f", 290 | \ "lua": "--lua-kinds=f", 291 | \ "matla": "--matlab-kinds=f", 292 | \ "pascal": "--pascal-kinds=f", 293 | \ "php": "--php-kinds=f", 294 | \ "python": "--python-kinds=fm --language-force=Python", 295 | \ "ruby": "--ruby-kinds=fF", 296 | \ "scheme": "--scheme-kinds=f", 297 | \ "sh": "--sh-kinds=f", 298 | \ "sql": "--sql-kinds=f", 299 | \ "tcl": "--tcl-kinds=m", 300 | \ "verilog": "--verilog-kinds=f", 301 | \ "vim": "--vim-kinds=f --language-force=Vim", 302 | \ "go": "--go-kinds=f --language-force=Go", 303 | \ "rust": "--rust-kinds=fPM", 304 | \ "ocaml": "--ocaml-kinds=mf", 305 | \ "dosini": "--iniconf-kinds=s --language-force=iniconf", 306 | \ "taskini": "--iniconf-kinds=s --language-force=iniconf", 307 | \ "ini": "--iniconf-kinds=s --language-force=iniconf", 308 | \ } 309 | let ft = (a:ft != '')? a:ft : getbufvar(a:bid, '&ft') 310 | let modified = getbufvar(a:bid, '&modified') 311 | let ctags = get(g:, 'quickui_ctags_exe', 'ctags') 312 | let filename = bufname(a:bid) 313 | let extname = fnamemodify(filename, ':e') 314 | let extras = get(get(g:, 'quickui_ctags_opts', {}), ft, get(parameters, ft, '')) 315 | let srcname = fnamemodify(filename, ':p') 316 | if modified || filename == '' 317 | if filename == '' || extname == '' 318 | let srcname = tempname() 319 | else 320 | let srcname = tempname() . '.' . extname 321 | endif 322 | let content = getbufline(a:bid, 1, '$') 323 | call writefile(content, srcname) 324 | unlet content 325 | endif 326 | if exists('g:quickui_tags_list') 327 | let extras = get(g:quickui_tags_list, ft, extras) 328 | endif 329 | let cmd = ctags . ' -n -u --fields=k ' . extras . ' -f- ' 330 | let output = quickui#utils#system(cmd . '"' . srcname . '"') 331 | if modified 332 | call delete(srcname) 333 | endif 334 | let items = [] 335 | for line in split(output, "\n") 336 | let line = substitute(line, '[\t\r\n ]*$', '', '') 337 | let item = split(line, "\t") 338 | if len(item) >= 4 339 | let ni = {} 340 | let ni.tag = item[0] " tagname 341 | let ni.line = str2nr(substitute(item[2], '[;"\s]', '', 'g')) 342 | let ni.mode = substitute(item[3], '[\r\n\t ]*$', '', 'g') 343 | let ni.text = '' 344 | let code = getbufline(a:bid, ni.line) 345 | if len(code) == 1 346 | let x = code[0] 347 | let ni.text = substitute(x, '^\s*\(.\{-}\)\s*$', '\1', '') 348 | endif 349 | let items += [ni] 350 | endif 351 | endfor 352 | return items 353 | endfunc 354 | 355 | 356 | "---------------------------------------------------------------------- 357 | " ctags vim help file 358 | "---------------------------------------------------------------------- 359 | function! quickui#tags#ctags_vim_help(bid) 360 | let content = getbufline(a:bid, 1, '$') 361 | let tags = [] 362 | let lnum = 0 363 | for text in content 364 | let lnum += 1 365 | let p1 = stridx(text, '*') 366 | if p1 < 0 367 | continue 368 | endif 369 | let p = matchstr(text, '\*\(\S\+\)\*') 370 | if p == '' 371 | continue 372 | endif 373 | let tag = {} 374 | let tag.tag = p 375 | let tag.line = lnum 376 | let sp = substitute(text, '^\s*\(.\{-}\)\s*$', '\1', '') 377 | let tag.text = tr(sp, "\t", ' ') 378 | let tag.mode = 't' 379 | call add(tags, tag) 380 | endfor 381 | return tags 382 | endfunc 383 | 384 | 385 | "---------------------------------------------------------------------- 386 | " query function list 387 | "---------------------------------------------------------------------- 388 | function! quickui#tags#function_list(bid, ft) 389 | let changedtick = getbufvar(a:bid, 'changedtick') 390 | let currenttick = getbufvar(a:bid, '__quickui_tags_tick', -100) 391 | let start = reltime() 392 | if currenttick != changedtick 393 | if &ft != 'help' 394 | let items = quickui#tags#ctags_function(a:bid, a:ft) 395 | else 396 | let items = quickui#tags#ctags_vim_help(a:bid) 397 | endif 398 | call setbufvar(a:bid, '__quickui_tags_func', items) 399 | call setbufvar(a:bid, '__quickui_tags_tick', changedtick) 400 | endif 401 | let items = getbufvar(a:bid, '__quickui_tags_func') 402 | if type(items) == v:t_string 403 | let items = quickui#tags#ctags_function(a:bid, a:ft) 404 | call setbufvar(a:bid, '__quickui_tags_func', items) 405 | call setbufvar(a:bid, '__quickui_tags_tick', changedtick) 406 | endif 407 | let g:quickui#tags#elapse = reltimestr(reltime(start)) 408 | " echo g:quickui#tags#elapse 409 | if a:ft == 'python' 410 | let output = [] 411 | for ni in items 412 | if ni.mode == 'f' 413 | if ni.text =~ '\v\s.*\:\s*\S+' 414 | continue 415 | endif 416 | endif 417 | let output += [ni] 418 | endfor 419 | return output 420 | endif 421 | return items 422 | endfunc 423 | 424 | 425 | 426 | -------------------------------------------------------------------------------- /autoload/quickui/terminal.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " terminal.vim - 4 | " 5 | " Created by skywind on 2020/02/03 6 | " Last Modified: 2020/02/03 10:31:33 7 | " 8 | "====================================================================== 9 | 10 | " vim: set noet fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : 11 | 12 | 13 | "---------------------------------------------------------------------- 14 | " terminal return 15 | "---------------------------------------------------------------------- 16 | let g:quickui#terminal#capture = [] 17 | let g:quickui#terminal#tmpname = '' 18 | 19 | 20 | "---------------------------------------------------------------------- 21 | " create a terminal popup 22 | "---------------------------------------------------------------------- 23 | function! quickui#terminal#create(cmd, opts) 24 | let w = get(a:opts, 'w', 80) 25 | let h = get(a:opts, 'h', 24) 26 | let winid = -1 27 | let title = has_key(a:opts, 'title')? (' ' . a:opts.title .' ') : '' 28 | let border = get(a:opts, 'border', g:quickui#style#border) 29 | let button = (get(a:opts, 'close', '') == 'button')? 1 : 0 30 | let color = get(a:opts, 'color', 'QuickTermBorder') 31 | let ww = w + ((border != 0)? 2 : 0) 32 | let hh = h + ((border != 0)? 2 : 0) 33 | let hwnd = {'opts':deepcopy(a:opts), 'code':-1} 34 | if !has_key(hwnd.opts, 'line') 35 | let limit1 = (&lines - 2) * 90 / 100 36 | let limit2 = (&lines - 2) 37 | if h + 4 < limit1 38 | let hwnd.opts.line = (limit1 - hh) / 2 39 | else 40 | let hwnd.opts.line = (limit2 - hh) / 2 41 | endif 42 | let hwnd.opts.line = (hwnd.opts.line < 1)? 1 : hwnd.opts.line 43 | endif 44 | if !has_key(hwnd.opts, 'col') 45 | let hwnd.opts.col = (&columns - ww) / 2 46 | let hwnd.opts.col = (hwnd.opts.col < 1)? 1 : hwnd.opts.col 47 | endif 48 | if has('nvim') == 0 49 | let opts = {'hidden': 1, 'term_rows':h, 'term_cols':w} 50 | let opts.term_kill = get(a:opts, 'term_kill', 'term') 51 | let opts.norestore = 1 52 | let opts.exit_cb = function('s:vim_term_exit') 53 | let opts.term_finish = 'close' 54 | let savedir = getcwd() 55 | if has_key(a:opts, 'cwd') 56 | call quickui#core#chdir(a:opts.cwd) 57 | endif 58 | let bid = term_start(a:cmd, opts) 59 | if has_key(a:opts, 'cwd') 60 | call quickui#core#chdir(savedir) 61 | endif 62 | if bid <= 0 63 | return -1 64 | endif 65 | let opts = {'maxwidth':w, 'maxheight':h, 'minwidth':w, 'minheight':h} 66 | let opts.wrap = 0 67 | let opts.mapping = 0 68 | let opts.title = title 69 | let opts.close = (button)? 'button' : 'none' 70 | let opts.border = border? [1,1,1,1,1,1,1,1,1] : repeat([0], 9) 71 | let opts.highlight = color 72 | let opts.borderchars = quickui#core#border_vim(border) 73 | let opts.drag = get(a:opts, 'drag', 1) 74 | let opts.resize = 0 75 | let opts.callback = function('s:vim_popup_callback') 76 | let winid = popup_create(bid, opts) 77 | call popup_move(winid, {'line':hwnd.opts.line, 'col':hwnd.opts.col}) 78 | let hwnd.winid = winid 79 | let g:quickui#terminal#current = hwnd 80 | let s:current = hwnd 81 | call popup_show(winid) 82 | let init = [] 83 | let init += ['setlocal nonumber norelativenumber scrolloff=0'] 84 | let init += ['setlocal signcolumn=no'] 85 | let init += ['setlocal bufhidden=wipe'] 86 | call quickui#core#win_execute(winid, init) 87 | else 88 | let bid = quickui#core#scratch_buffer('terminal', []) 89 | let opts = {'focusable':1, 'style':'minimal', 'relative':'editor'} 90 | let opts.width = w 91 | let opts.height = h 92 | let opts.row = hwnd.opts.line - 1 + ((border > 0)? 1 : 0) 93 | let opts.col = hwnd.opts.col - 1 + ((border > 0)? 1 : 0) 94 | if has('nvim-0.6.0') 95 | let opts.noautocmd = 1 96 | endif 97 | let winid = nvim_open_win(bid, 1, opts) 98 | let hwnd.winid = winid 99 | let hwnd.background = -1 100 | if winid < 0 101 | return -1 102 | endif 103 | let cc = get(g:, 'terminal_color_0', 0) 104 | let hl = 'Normal:'.cc.',NonText:'.cc.',EndOfBuffer:'.cc 105 | " silent! call nvim_win_set_option(winid, 'winhl', hl) 106 | call setwinvar(winid, '&winhighlight', 'NormalFloat:Normal') 107 | if border > 0 108 | let title = has_key(a:opts, 'title')? ' ' . a:opts.title . ' ':'' 109 | let back = quickui#utils#make_border(w, h, border, title, button) 110 | let nbid = quickui#core#scratch_buffer('terminalborder', back) 111 | let op = {'relative':'editor', 'focusable':0, 'style':'minimal'} 112 | let op.width = w + 2 113 | let op.height = h + 2 114 | let pos = nvim_win_get_config(winid) 115 | let op.row = hwnd.opts.line - 1 116 | let op.col = hwnd.opts.col - 1 117 | if has('nvim-0.6.0') 118 | let op.noautocmd = 1 119 | endif 120 | let background = nvim_open_win(nbid, 0, op) 121 | call nvim_win_set_option(background, 'winhl', 'Normal:'. color) 122 | let hwnd.background = background 123 | endif 124 | call nvim_set_current_win(winid) 125 | setlocal nomodified 126 | let opts = {'width': w, 'height':h} 127 | let opts.on_exit = function('s:nvim_term_exit') 128 | if has_key(a:opts, 'cwd') 129 | let opts.cwd = a:opts.cwd 130 | endif 131 | call termopen(a:cmd, opts) 132 | let g:quickui#terminal#current = hwnd 133 | let s:current = hwnd 134 | let init = [] 135 | let init += ['setlocal nonumber norelativenumber scrolloff=0'] 136 | let init += ['setlocal signcolumn=no'] 137 | let init += ['setlocal bufhidden=wipe'] 138 | call quickui#core#win_execute(winid, init) 139 | startinsert 140 | endif 141 | return hwnd 142 | endfunc 143 | 144 | 145 | "---------------------------------------------------------------------- 146 | " read back capture 147 | "---------------------------------------------------------------------- 148 | function! s:capture_read() 149 | let g:quickui#terminal#capture = [] 150 | if g:quickui#terminal#tmpname != '' 151 | let tmpname = g:quickui#terminal#tmpname 152 | let g:quickui#terminal#tmpname = '' 153 | if filereadable(tmpname) 154 | silent! let g:quickui#terminal#capture = readfile(tmpname) 155 | call delete(tmpname) 156 | endif 157 | endif 158 | endfunc 159 | 160 | 161 | "---------------------------------------------------------------------- 162 | " terminal exit_cb 163 | "---------------------------------------------------------------------- 164 | function! s:vim_term_exit(job, message) 165 | if exists('s:current') 166 | let hwnd = s:current 167 | let hwnd.code = a:message 168 | endif 169 | endfunc 170 | 171 | 172 | "---------------------------------------------------------------------- 173 | " popup callback 174 | "---------------------------------------------------------------------- 175 | function! s:vim_popup_callback(winid, code) 176 | if exists('s:current') 177 | let hwnd = s:current 178 | let hwnd.winid = -1 179 | call s:capture_read() 180 | if has_key(hwnd.opts, 'callback') 181 | call call(hwnd.opts.callback, [hwnd.code]) 182 | endif 183 | endif 184 | endfunc 185 | 186 | 187 | "---------------------------------------------------------------------- 188 | " neovim exit 189 | "---------------------------------------------------------------------- 190 | function! s:nvim_term_exit(jobid, data, event) 191 | if exists('s:current') 192 | let hwnd = s:current 193 | let hwnd.code = a:data 194 | if hwnd.winid >= 0 195 | call nvim_win_close(hwnd.winid, 0) 196 | endif 197 | if hwnd.background >= 0 198 | call nvim_win_close(hwnd.background, 0) 199 | endif 200 | let hwnd.winid = -1 201 | let hwnd.background = -1 202 | call s:capture_read() 203 | if has_key(hwnd.opts, 'callback') 204 | call call(hwnd.opts.callback, [hwnd.code]) 205 | endif 206 | endif 207 | endfunc 208 | 209 | 210 | "---------------------------------------------------------------------- 211 | " open terminal in popup window 212 | "---------------------------------------------------------------------- 213 | function! quickui#terminal#open(cmd, opts) 214 | let opts = deepcopy(a:opts) 215 | let border = get(a:opts, 'border', g:quickui#style#border) 216 | if border == 0 217 | if has_key(opts, 'title') 218 | unlet opts['title'] 219 | endif 220 | if has_key(opts, 'close') 221 | unlet opts['close'] 222 | endif 223 | endif 224 | if has_key(opts, 'callback') 225 | if type(opts.callback) == v:t_string 226 | if opts.callback == '' 227 | unlet opts['callback'] 228 | endif 229 | endif 230 | endif 231 | if has_key(opts, 'w') 232 | let opts.w = quickui#utils#read_size(opts.w, &columns) 233 | endif 234 | if has_key(opts, 'h') 235 | let opts.h = quickui#utils#read_size(opts.h, &lines) 236 | endif 237 | let g:quickui#terminal#capture = [] 238 | let g:quickui#terminal#tmpname = '' 239 | let $VIM_INPUT = '' 240 | let $VIM_CAPTURE = '' 241 | if has_key(opts, 'input') 242 | if has('win32') || has('win64') || has('win95') || has('win16') 243 | let tmpname = fnamemodify(tempname(), ':h') . '\quickui1.txt' 244 | else 245 | let tmpname = fnamemodify(tempname(), ':h') . '/quickui1.txt' 246 | endif 247 | call writefile(opts.input, tmpname) 248 | let $VIM_INPUT = tmpname 249 | endif 250 | if has_key(opts, 'capture') 251 | if opts.capture 252 | if has('win32') || has('win64') || has('win95') || has('win16') 253 | let tmpname = fnamemodify(tempname(), ':h') . '\quickui2.txt' 254 | else 255 | let tmpname = fnamemodify(tempname(), ':h') . '/quickui2.txt' 256 | endif 257 | let g:quickui#terminal#tmpname = tmpname 258 | let $VIM_CAPTURE = tmpname 259 | if filereadable(tmpname) 260 | call delete(tmpname) 261 | endif 262 | endif 263 | unlet opts['capture'] 264 | endif 265 | return quickui#terminal#create(a:cmd, opts) 266 | endfunc 267 | 268 | 269 | "---------------------------------------------------------------------- 270 | " dialog exit 271 | "---------------------------------------------------------------------- 272 | function! s:dialog_callback(code) 273 | let args = {} 274 | let args.code = a:code 275 | let args.capture = g:quickui#terminal#capture 276 | call call(s:dialog_cb, [args]) 277 | endfunc 278 | 279 | 280 | "---------------------------------------------------------------------- 281 | " dialog: run command line tool and capture result 282 | " the callback function changes to a new prototype: 283 | " function! Callback(args), where args is a tuple of (code, capture) 284 | " where capture is a list of text lines in the $VIM_CAPTURE file 285 | "---------------------------------------------------------------------- 286 | function! quickui#terminal#dialog(cmd, opts) 287 | let opts = deepcopy(a:opts) 288 | let opts.macros = quickui#core#expand_macros() 289 | if has_key(opts, 'prepare') 290 | call call(opts.prepare, [opts]) 291 | endif 292 | let command = a:cmd 293 | for [key, val] in items(opts.macros) 294 | let replace = (key[0] != '<')? '$('.key.')' : key 295 | if key[0] != '<' 296 | exec 'let $' . key . ' = val' 297 | endif 298 | let command = quickui#core#string_replace(command, replace, val) 299 | if has_key(opts, 'cwd') 300 | let opts.cwd = quickui#core#string_replace(opts.cwd, replace, val) 301 | endif 302 | endfor 303 | let cwd = get(opts, 'cwd', '') 304 | if cwd != '' 305 | let previous = getcwd() 306 | call quickui#core#chdir(cwd) 307 | let opts.macros['VIM_CWD'] = getcwd() 308 | let opts.macros['VIM_RELDIR'] = expand("%:h:.") 309 | let opts.macros['VIM_RELNAME'] = expand("%:p:.") 310 | let opts.macros['VIM_CFILE'] = expand("") 311 | let opts.macros['VIM_DIRNAME'] = fnamemodify(opts.macros['VIM_CWD'], ':t') 312 | let opts.macros[''] = opts.macros['VIM_CWD'] 313 | call quickui#core#chdir(previous) 314 | endif 315 | let pause = get(opts, 'pause', 0) 316 | let command = quickui#core#write_script(command, pause) 317 | if has_key(opts, 'callback') 318 | let l:F2 = opts.callback 319 | if type(l:F2) == v:t_string 320 | if l:F2 != '' 321 | let s:dialog_cb = function(l:F2) 322 | let opts.callback = function('s:dialog_callback') 323 | let opts.capture = 1 324 | endif 325 | elseif type(l:F2) == v:t_func 326 | let s:dialog_cb = function(l:F2) 327 | let opts.callback = function('s:dialog_callback') 328 | let opts.capture = 1 329 | endif 330 | unlet l:F2 331 | endif 332 | if has_key(opts, 'cwd') 333 | if opts.cwd == '' 334 | unlet opts['cwd'] 335 | endif 336 | endif 337 | return quickui#terminal#open(command, opts) 338 | endfunc 339 | 340 | 341 | -------------------------------------------------------------------------------- /autoload/quickui/textbox.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " textbox.vim - 4 | " 5 | " Created by skywind on 2019/12/27 6 | " Last Modified: 2020/02/20 02:29 7 | " 8 | "====================================================================== 9 | 10 | " vim: set noet fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : 11 | 12 | 13 | "---------------------------------------------------------------------- 14 | " reposition 15 | "---------------------------------------------------------------------- 16 | function! quickui#textbox#reposition() 17 | let curline = line('.') 18 | exec 'normal! zz' 19 | let height = winheight(0) 20 | let moveup = winline() - 1 21 | if moveup > 0 22 | exec "normal " . moveup . "\" 23 | exec ":" . curline 24 | endif 25 | let size = line('$') 26 | let winline = winline() 27 | let topline = curline - winline + 1 28 | let botline = topline + height - 1 29 | let disline = botline - size 30 | if disline > 0 31 | exec 'normal ggG' 32 | exec ':' . curline 33 | exec 'normal G' 34 | exec ':' . curline 35 | endif 36 | endfunc 37 | 38 | 39 | "---------------------------------------------------------------------- 40 | " create textbox 41 | "---------------------------------------------------------------------- 42 | function! s:vim_create_textbox(textlist, opts) 43 | let winid = popup_create(a:textlist, {'hidden':1, 'wrap':1}) 44 | let opts = {} 45 | let opts.maxheight = &lines - 2 46 | let opts.maxwidth = &columns 47 | if has_key(a:opts, 'w') 48 | let opts.minwidth = a:opts.w 49 | let opts.maxwidth = a:opts.w 50 | endif 51 | if has_key(a:opts, 'h') 52 | let opts.minheight = a:opts.h 53 | let opts.maxheight = a:opts.h 54 | endif 55 | if has_key(a:opts, 'line') && has_key(a:opts, 'col') 56 | let opts.line = a:opts.line 57 | let opts.col = a:opts.col 58 | endif 59 | if len(opts) > 0 60 | call popup_move(winid, opts) 61 | endif 62 | if has_key(a:opts, 'line') == 0 || has_key(a:opts, 'col') == 0 63 | call quickui#utils#center(winid) 64 | endif 65 | let opts = {'mapping':0, 'cursorline':0, 'drag':1} 66 | let border = get(a:opts, 'border', g:quickui#style#border) 67 | let opts.border = [0,0,0,0,0,0,0,0,0] 68 | if border > 0 69 | let opts.borderchars = quickui#core#border_vim(border) 70 | let opts.border = [1,1,1,1,1,1,1,1,1] 71 | let opts.close = 'button' 72 | endif 73 | let opts.padding = [0,1,0,1] 74 | if has_key(a:opts, 'title') && (a:opts.title != '') 75 | let opts.title = ' '. a:opts.title . ' ' 76 | endif 77 | let opts.filter = function('s:popup_filter') 78 | let opts.callback = function('s:popup_exit') 79 | let opts.resize = get(a:opts, 'resize', 0) 80 | let opts.highlight = get(a:opts, 'color', 'QuickBG') 81 | if has_key(a:opts, 'index') 82 | let index = (a:opts.index < 1)? 1 : a:opts.index 83 | let opts.firstline = index 84 | call win_execute(winid, ':' . index) 85 | endif 86 | let local = quickui#core#popup_local(winid) 87 | let local.winid = winid 88 | let local.keymap = quickui#utils#keymap() 89 | let local.keymap['x'] = 'ESC' 90 | let local.opts = deepcopy(a:opts) 91 | if has_key(a:opts, 'callback') 92 | let local.callback = a:opts.callback 93 | endif 94 | if has_key(a:opts, 'list') 95 | if a:opts.list 96 | call win_execute(winid, 'setl list') 97 | else 98 | call win_execute(winid, 'setl nolist') 99 | endif 100 | endif 101 | let bc = get(a:opts, 'bordercolor', 'QuickBorder') 102 | let opts.borderhighlight = [bc, bc, bc, bc] 103 | if has_key(a:opts, 'tabstop') 104 | call win_execute(winid, 'setlocal tabstop=' . get(a:opts, 'tabstop', 4)) 105 | endif 106 | if has_key(a:opts, 'syntax') 107 | call win_execute(winid, 'set ft=' . fnameescape(a:opts.syntax)) 108 | endif 109 | let cursor = get(a:opts, 'cursor', -1) 110 | call setbufvar(winbufnr(winid), '__quickui_cursor__', cursor) 111 | call setbufvar(winbufnr(winid), '__quickui_line__', -1) 112 | if get(a:opts, 'number', 0) != 0 113 | call win_execute(winid, 'setlocal number') 114 | endif 115 | if cursor < 0 116 | call win_execute(winid, 'setlocal nocursorline') 117 | endif 118 | if has_key(a:opts, 'bordercolor') 119 | let c = a:opts.bordercolor 120 | let opts.borderhighlight = [c, c, c, c] 121 | endif 122 | call popup_setoptions(winid, opts) 123 | call win_execute(winid, 'setlocal scrolloff=0') 124 | if has_key(a:opts, 'command') 125 | call quickui#core#win_execute(winid, a:opts.command) 126 | endif 127 | call quickui#utils#update_cursor(winid) 128 | call popup_show(winid) 129 | redraw 130 | return winid 131 | endfunc 132 | 133 | 134 | "---------------------------------------------------------------------- 135 | " close textbox 136 | "---------------------------------------------------------------------- 137 | function! quickui#textbox#close(winid) 138 | call popup_close(a:winid) 139 | endfunc 140 | 141 | 142 | "---------------------------------------------------------------------- 143 | " exit and quit 144 | "---------------------------------------------------------------------- 145 | function! s:popup_exit(winid, code) 146 | let topline = quickui#utils#get_topline(a:winid) 147 | let g:quickui#textbox#topline = topline 148 | let local = quickui#core#popup_local(a:winid) 149 | let g:quickui#textbox#current = local 150 | call quickui#core#popup_clear(a:winid) 151 | if has_key(local, 'callback') 152 | let l:F = function(local.callback) 153 | call l:F(topline) 154 | unlet l:F 155 | endif 156 | endfunc 157 | 158 | 159 | "---------------------------------------------------------------------- 160 | " filter 161 | "---------------------------------------------------------------------- 162 | function! s:popup_filter(winid, key) 163 | let local = quickui#core#popup_local(a:winid) 164 | let keymap = local.keymap 165 | if a:key == "\" || a:key == "\" || a:key == "\" 166 | call popup_close(a:winid, 0) 167 | return 1 168 | elseif a:key == " " || a:key == "x" || a:key == "q" 169 | call popup_close(a:winid, 0) 170 | return 1 171 | elseif a:key == "\" 172 | let pos = getmousepos() 173 | if pos.winid == a:winid && pos.line > 0 174 | if get(local.opts, 'exit_on_click', 0) != 0 175 | call popup_close(a:winid, 0) 176 | return 1 177 | endif 178 | endif 179 | elseif a:key == ':' || a:key == '/' || a:key == '?' 180 | call quickui#utils#search_or_jump(a:winid, a:key) 181 | noautocmd call quickui#utils#update_cursor(a:winid) 182 | redraw 183 | return 1 184 | elseif has_key(keymap, a:key) 185 | let key = keymap[a:key] 186 | if key == "ENTER" || key == "ESC" 187 | call popup_close(a:winid, 0) 188 | return 1 189 | elseif key == 'NEXT' || key == 'PREV' 190 | call quickui#utils#search_next(a:winid, key) 191 | noautocmd call quickui#utils#update_cursor(a:winid) 192 | redraw 193 | return 1 194 | else 195 | noautocmd call quickui#utils#scroll(a:winid, key) 196 | redraw 197 | noautocmd call quickui#utils#update_cursor(a:winid) 198 | endif 199 | endif 200 | return popup_filter_yesno(a:winid, a:key) 201 | endfunc 202 | 203 | 204 | "---------------------------------------------------------------------- 205 | " create text box in neovim 206 | "---------------------------------------------------------------------- 207 | function! s:nvim_create_textbox(textlist, opts) 208 | if type(a:textlist) == v:t_list 209 | let bid = quickui#core#scratch_buffer('textbox', a:textlist) 210 | elseif type(a:textlist) == v:t_string 211 | let bid = quickui#core#scratch_buffer('textbox', [a:textlist]) 212 | elseif type(a:textlist) == v:t_number 213 | let bid = a:textlist 214 | endif 215 | let opts = {'focusable':1, 'style':'minimal', 'relative':'editor'} 216 | let opts.width = get(a:opts, 'w', 80) 217 | let opts.height = get(a:opts, 'h', 24) 218 | let opts.row = get(a:opts, 'line', 1) - 1 219 | let opts.col = get(a:opts, 'col', 1) - 1 220 | let border = get(a:opts, 'border', g:quickui#style#border) 221 | if border > 0 && get(g:, 'quickui_nvim_simulate_border', 1) != 0 222 | let opts.row += 1 223 | let opts.col += 1 224 | endif 225 | if has('nvim-0.6.0') 226 | let opts.noautocmd = 1 227 | endif 228 | let winid = nvim_open_win(bid, 0, opts) 229 | if has_key(a:opts, 'line') == 0 && has_key(a:opts, 'col') == 0 230 | call quickui#utils#center(winid) 231 | endif 232 | let color = get(a:opts, 'color', 'QuickBG') 233 | call nvim_win_set_option(winid, 'winhl', 'Normal:'. color) 234 | let opts.w = nvim_win_get_width(winid) 235 | let opts.h = nvim_win_get_height(winid) 236 | let button = (get(a:opts, 'close', '') == 'button')? 1 : 0 237 | let background = -1 238 | if border > 0 && get(g:, 'quickui_nvim_simulate_border', 1) != 0 239 | let title = has_key(a:opts, 'title')? ' ' . a:opts.title . ' ' : '' 240 | let w = opts.w 241 | let h = opts.h 242 | let back = quickui#utils#make_border(w, h, border, title, button) 243 | let nbid = quickui#core#scratch_buffer('textboxborder', back) 244 | let op = {'relative':'editor', 'focusable':1, 'style':'minimal'} 245 | let op.width = opts.w + 2 246 | let op.height = opts.h + 2 247 | let pos = nvim_win_get_config(winid) 248 | let op.row = pos.row - 1 249 | let op.col = pos.col - 1 250 | let bordercolor = get(a:opts, 'bordercolor', 'QuickBorder') 251 | if has('nvim-0.6.0') 252 | let op.noautocmd = 1 253 | endif 254 | let background = nvim_open_win(nbid, 0, op) 255 | call nvim_win_set_option(background, 'winhl', 'Normal:'. bordercolor) 256 | endif 257 | let init = ['syn clear'] 258 | if has_key(a:opts, 'tabstop') 259 | let init += ['setlocal tabstop='. get(a:opts, 'tabstop', 4)] 260 | endif 261 | let init += ['setlocal signcolumn=no'] 262 | let init += ['setlocal scrolloff=0'] 263 | let init += ['setlocal wrap'] 264 | let init += ['noautocmd exec "normal! gg"'] 265 | if get(a:opts, 'number', 0) != 0 266 | let init += ['setlocal number'] 267 | endif 268 | if has_key(a:opts, 'syntax') 269 | let init += ['set ft='.fnameescape(a:opts.syntax)] 270 | " echo "syntax: ". a:opts.syntax 271 | endif 272 | let cursor = get(a:opts, 'cursor', -1) 273 | call setbufvar(bid, '__quickui_cursor__', cursor) 274 | call setbufvar(bid, '__quickui_line__', -1) 275 | if has_key(a:opts, 'index') 276 | let index = (a:opts.index < 1)? 1 : a:opts.index 277 | let opts.firstline = index 278 | let init += ['noautocmd exec "normal! gg"'] 279 | if index > 1 280 | let init += ['noautocmd exec "normal! '. (index - 1) . '\"'] 281 | endif 282 | endif 283 | call quickui#core#win_execute(winid, init) 284 | let highlight = 'Normal:'.color.',NonText:'.color.',EndOfBuffer:'.color 285 | call nvim_win_set_option(winid, 'winhl', highlight) 286 | if has_key(a:opts, 'command') 287 | call quickui#core#win_execute(winid, a:opts.command) 288 | endif 289 | noautocmd call quickui#utils#update_cursor(winid) 290 | let local = {} 291 | let local.winid = winid 292 | let local.keymap = quickui#utils#keymap() 293 | let local.keymap['x'] = 'ESC' 294 | let local.opts = deepcopy(a:opts) 295 | noautocmd redraw 296 | while 1 297 | noautocmd redraw! 298 | try 299 | let code = getchar() 300 | catch /^Vim:Interrupt$/ 301 | let code = "\" 302 | endtry 303 | let ch = (type(code) == v:t_number)? nr2char(code) : code 304 | if ch == "\" || ch == "\" 305 | break 306 | elseif ch == ' ' || ch == 'x' || ch == 'q' 307 | break 308 | elseif ch == "\" 309 | if v:mouse_winid == winid 310 | if v:mouse_lnum > 0 311 | if get(a:opts, 'exit_on_click', 0) != 0 312 | break 313 | endif 314 | endif 315 | elseif v:mouse_winid == background 316 | if button != 0 && v:mouse_lnum == 1 317 | if v:mouse_col == opts.w + 2 318 | break 319 | endif 320 | endif 321 | endif 322 | elseif ch == '/' || ch == '?' || ch == ':' 323 | call quickui#utils#search_or_jump(winid, ch) 324 | noautocmd call quickui#utils#update_cursor(winid) 325 | elseif has_key(local.keymap, ch) 326 | let key = local.keymap[ch] 327 | if key == 'ENTER' || key == 'ESC' 328 | break 329 | elseif key == 'NEXT' || key == 'PREV' 330 | call quickui#utils#search_next(winid, key) 331 | noautocmd call quickui#utils#update_cursor(winid) 332 | else 333 | noautocmd call quickui#utils#scroll(winid, key) 334 | noautocmd call quickui#utils#update_cursor(winid) 335 | endif 336 | endif 337 | endwhile 338 | let topline = quickui#utils#get_topline(winid) 339 | let g:quickui#textbox#topline = topline 340 | call nvim_win_close(winid, 0) 341 | if background >= 0 342 | call nvim_win_close(background, 0) 343 | endif 344 | let g:quickui#textbox#current = local 345 | if has_key(a:opts, 'callback') 346 | let F = function(a:opts.callback) 347 | call F(topline) 348 | endif 349 | return topline 350 | endfunc 351 | 352 | 353 | "---------------------------------------------------------------------- 354 | " cross platform create 355 | "---------------------------------------------------------------------- 356 | function! quickui#textbox#create(textlist, opts) 357 | if g:quickui#core#has_nvim == 0 358 | return s:vim_create_textbox(a:textlist, a:opts) 359 | else 360 | return s:nvim_create_textbox(a:textlist, a:opts) 361 | endif 362 | endfunc 363 | 364 | 365 | "---------------------------------------------------------------------- 366 | " open 367 | "---------------------------------------------------------------------- 368 | function! quickui#textbox#open(textlist, opts) 369 | let maxheight = (&lines) * 70 / 100 370 | let maxwidth = (&columns) * 80 / 100 371 | let opts = deepcopy(a:opts) 372 | let opts.close = 'button' 373 | let maxheight = has_key(opts, 'maxheight')? opts.maxheight : maxheight 374 | let maxwidth = has_key(opts, 'maxwidth')? opts.maxwidth : maxwidth 375 | if has_key(opts, 'h') == 0 376 | let size = (type(a:textlist) == v:t_list)? len(a:textlist) : 20 377 | let opts.h = (size < maxheight)? size : maxheight 378 | endif 379 | if has_key(opts, 'w') == 0 380 | if type(a:textlist) == v:t_list 381 | let opts.w = 1 382 | for line in a:textlist 383 | let size = strdisplaywidth(line) 384 | let opts.w = (size < opts.w)? opts.w : size 385 | endfor 386 | if opts.w > maxwidth 387 | let opts.w = maxwidth 388 | endif 389 | if get(a:opts, 'number', 0) != 0 390 | let opts.w += len(string(len(a:textlist))) + 3 391 | endif 392 | endif 393 | endif 394 | if has_key(opts, 'h') 395 | let minheight = get(opts, 'minheight', 1) 396 | let minheight = (minheight < 1)? 1 : minheight 397 | let opts.h = (opts.h < minheight)? minheight : opts.h 398 | endif 399 | if has_key(opts, 'w') 400 | let minwidth = get(opts, 'minwidth', 20) 401 | let minwidth = (minwidth < 1)? 1 : minwidth 402 | let opts.w = (opts.w < minwidth)? minwidth : opts.w 403 | endif 404 | call quickui#textbox#create(a:textlist, opts) 405 | endfunc 406 | 407 | 408 | "---------------------------------------------------------------------- 409 | " run shell command and display result in the text box 410 | "---------------------------------------------------------------------- 411 | function! quickui#textbox#command(cmd, opts) 412 | let text = quickui#utils#system(a:cmd) 413 | let linelist = [] 414 | let enc = get(g:, 'quickui_shell_encoding', '') 415 | for line in split(text, "\n") 416 | if enc != '' 417 | let line = iconv(line, enc, &encoding) 418 | endif 419 | let line = trim(line, "\r") 420 | let linelist += [line] 421 | endfor 422 | call quickui#textbox#open(linelist, a:opts) 423 | endfunc 424 | 425 | 426 | "---------------------------------------------------------------------- 427 | " testing suit 428 | "---------------------------------------------------------------------- 429 | if 0 430 | let lines = [] 431 | for i in range(2000) 432 | let lines += ['printf("%d\n", ' . (i + 1) . ');'] 433 | endfor 434 | let opts = {} 435 | let opts.index = 30 436 | let opts.resize = 1 437 | let opts.title = "title" 438 | let opts.syntax = "cpp" 439 | let opts.color = "QuickBox" 440 | let opts.border = 0 441 | " let opts.bordercolor = "QuickBG" 442 | let opts.cursor = 38 443 | let opts.number = 1 444 | " let opts.exit_on_click = 0 445 | let winid = quickui#textbox#open(lines, opts) 446 | " call getchar() 447 | " call quickui#textbox#close(winid) 448 | endif 449 | 450 | 451 | 452 | 453 | -------------------------------------------------------------------------------- /autoload/quickui/tools.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " tools.vim - 4 | " 5 | " Created by skywind on 2019/12/23 6 | " Last Modified: 2021/11/30 14:43 7 | " 8 | "====================================================================== 9 | 10 | " vim: set noet fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : 11 | 12 | 13 | "---------------------------------------------------------------------- 14 | " list buffer ids 15 | "---------------------------------------------------------------------- 16 | function! s:buffer_list() 17 | let l:ls_cli = get(g:, 'quickui_buffer_list_cli', 'ls t') 18 | redir => buflist 19 | silent execute l:ls_cli 20 | redir END 21 | let bids = [] 22 | for curline in split(buflist, '\n') 23 | if curline =~ '^\s*\d\+' 24 | let bid = str2nr(matchstr(curline, '^\s*\zs\d\+')) 25 | let bids += [bid] 26 | endif 27 | endfor 28 | return bids 29 | endfunc 30 | 31 | 32 | "---------------------------------------------------------------------- 33 | " get default width 34 | "---------------------------------------------------------------------- 35 | function! s:get_tools_width() 36 | let width = get(g:, 'quickui_tools_width', 70) 37 | endfunc 38 | 39 | 40 | "---------------------------------------------------------------------- 41 | " locals 42 | "---------------------------------------------------------------------- 43 | let s:keymaps = '123456789abcdefimnopqrstuvwxyz' 44 | 45 | 46 | "---------------------------------------------------------------------- 47 | " switch buffer callback 48 | "---------------------------------------------------------------------- 49 | function! quickui#tools#buffer_switch(bid) 50 | let switch = get(g:, 'quickui_switch_mode', &switchbuf) 51 | let code = g:quickui#listbox#current.tag 52 | let name = fnamemodify(bufname(a:bid), ':p') 53 | let opts = {} 54 | let bid = str2nr('' . a:bid) 55 | if code == '' 56 | let opts.switch = get(g:, 'quickui_switch_enter', switch) 57 | call quickui#utils#switch(bid, opts) 58 | elseif code == '1' 59 | let opts.switch = get(g:, 'quickui_switch_space', switch) 60 | call quickui#utils#switch(bid, opts) 61 | elseif code == '2' 62 | exec 'b '. a:bid 63 | elseif code == '3' 64 | exec 'vs' 65 | exec 'b '. a:bid 66 | elseif code == '4' 67 | exec 'split' 68 | exec 'b '. a:bid 69 | elseif code == '5' 70 | exec 'tab split' 71 | exec 'b '. a:bid 72 | elseif code == '6' 73 | exec 'tab drop ' . fnameescape(name) 74 | endif 75 | endfunc 76 | 77 | 78 | "---------------------------------------------------------------------- 79 | " get content 80 | "---------------------------------------------------------------------- 81 | function! quickui#tools#list_buffer(switch) 82 | let bids = s:buffer_list() 83 | let content = [] 84 | let index = 0 85 | let current = -1 86 | let bufnr = bufnr() 87 | let s:switch = a:switch 88 | for bid in bids 89 | let key = (index < len(s:keymaps))? strpart(s:keymaps, index, 1) : '' 90 | let text = '[' . ((key == '')? ' ' : ('&' . key)) . "]\t" 91 | let text .= "\t" 92 | let name = fnamemodify(bufname(bid), ':p') 93 | let main = fnamemodify(name, ':t') 94 | let path = fnamemodify(name, ':h') 95 | let buftype = getbufvar(bid, '&buftype') 96 | if main == '' 97 | continue 98 | elseif buftype == 'nofile' || buftype == 'quickfix' 99 | continue 100 | endif 101 | let text = text . main . " " . "(" . bid . ")\t" . path 102 | let cmd = 'call quickui#tools#buffer_switch(' . bid . ')' 103 | if a:switch != '' 104 | " let cmd = a:switch . ' ' . fnameescape(name) 105 | endif 106 | let content += [[text, cmd]] 107 | if bid == bufnr() 108 | let current = index 109 | endif 110 | let index += 1 111 | endfor 112 | let opts = {'title': 'Switch Buffer', 'index':current, 'close':'button'} 113 | let opts.border = g:quickui#style#border 114 | let opts.keymap = {} 115 | let opts.keymap["\"] = 'TAG:1' 116 | let opts.keymap["\"] = 'TAG:2' 117 | let opts.keymap["\"] = 'TAG:3' 118 | let opts.keymap["\"] = 'TAG:4' 119 | let opts.keymap["\"] = 'TAG:5' 120 | let opts.keymap["\"] = 'TAG:6' 121 | if exists('g:quickui_tools_width') 122 | let opts.w = quickui#utils#tools_width() 123 | endif 124 | " let opts.syntax = 'cpp' 125 | let maxheight = (&lines) * 60 / 100 126 | if len(content) > maxheight 127 | let opts.h = maxheight 128 | endif 129 | if len(content) == 0 130 | redraw 131 | echohl ErrorMsg 132 | echo "Empty buffer list" 133 | echohl None 134 | return -1 135 | endif 136 | call quickui#listbox#open(content, opts) 137 | endfunc 138 | 139 | 140 | "---------------------------------------------------------------------- 141 | " list function 142 | "---------------------------------------------------------------------- 143 | function! quickui#tools#list_function() 144 | let ctags = get(g:, 'quickui_ctags_exe', 'ctags') 145 | if !executable(ctags) 146 | let msg = 'Not find ctags, add to $PATH or specify in ' 147 | call quickui#utils#errmsg(msg . 'g:quickui_ctags_exe') 148 | return -1 149 | endif 150 | let items = quickui#tags#function_list(bufnr(), &ft) 151 | if len(items) == 0 152 | call quickui#utils#errmsg('No content !') 153 | return -2 154 | endif 155 | let content = [] 156 | let cursor = -1 157 | let index = 0 158 | let ln = line('.') 159 | let maxsize = (&columns) * 60 / 100 160 | let maxheight = (&lines) * 60 / 100 161 | let maxwidth = 0 162 | let indents = get(g:, 'quickui_tags_indent', {}) 163 | for item in items 164 | if ln >= item.line 165 | let cursor = index 166 | endif 167 | let index += 1 168 | let space = get(indents, item.mode, '') 169 | let text = '' . item.mode . '' . " \t" . space . item.text 170 | let text = text . ' [:' . item.line . ']' 171 | let maxwidth = (maxwidth < len(text))? len(text) : maxwidth 172 | let text = substitute(text, '&', '&&', 'g') 173 | let content += [[text, ':' . item.line]] 174 | endfor 175 | let opts = {'title': 'Function List', 'close':'button'} 176 | if cursor >= 0 177 | let opts.index = cursor 178 | endif 179 | let limit = &columns * 90 / 100 180 | let opts.h = len(content) 181 | let opts.h = (opts.h < maxheight)? opts.h : maxheight 182 | let opts.w = (maxwidth < limit)? maxwidth : limit 183 | if opts.w < maxsize 184 | let opts.w = (opts.w < 60)? 60 : opts.w 185 | endif 186 | let opts.syntax = 'qui_func' 187 | if exists('g:quickui_tools_width') 188 | let opts.w = quickui#utils#tools_width() 189 | endif 190 | " let content += ["1\t".repeat('0', 100)] 191 | call quickui#listbox#open(content, opts) 192 | return 0 193 | endfunc 194 | 195 | 196 | "---------------------------------------------------------------------- 197 | " preview register in popup and choose to paste 198 | "---------------------------------------------------------------------- 199 | function! quickui#tools#list_register() 200 | endfunc 201 | 202 | 203 | "---------------------------------------------------------------------- 204 | " display python help in the textbox 205 | "---------------------------------------------------------------------- 206 | function! quickui#tools#python_help(word) 207 | let python = get(g:, 'quickui_tools_python', '') 208 | if python == '' 209 | if executable('python') 210 | let python = 'python' 211 | elseif executable('python3') 212 | let python = 'python3' 213 | elseif executable('python2') 214 | let python = 'python2' 215 | endif 216 | endif 217 | if a:word == '' 218 | let text = getline('.') 219 | let pre = text[:col('.') - 1] 220 | let suf = text[col('.'):] 221 | let word = matchstr(pre, "[A-Za-z0-9_.]*$") 222 | let word = word . matchstr(suf, "^[A-Za-z0-9_]*") 223 | else 224 | let word = a:word 225 | endif 226 | let cmd = python . ' -m pydoc ' . shellescape(word) 227 | let title = 'PyDoc <'. a:word . '>' 228 | let opts = {'title':title} 229 | let opts.color = 'QuickBG' 230 | " let opts.bordercolor = 'QuickBG' 231 | let opts.tabstop = 12 232 | call quickui#textbox#command(cmd, opts) 233 | endfunc 234 | 235 | 236 | "---------------------------------------------------------------------- 237 | " display messages 238 | "---------------------------------------------------------------------- 239 | function! quickui#tools#display_messages() 240 | let x = '' 241 | redir => x 242 | silent! messages 243 | redir END 244 | let x = substitute(x, '[\n\r]\+\%$', '', 'g') 245 | let content = filter(split(x, "\n"), 'v:key != ""') 246 | if len(content) == 0 247 | call quickui#utils#errmsg('Empty messages') 248 | return -1 249 | endif 250 | let opts = {"close":"button", "title":"Vim Messages"} 251 | if exists('g:quickui_tools_width') 252 | let opts.w = quickui#utils#tools_width() 253 | endif 254 | call quickui#textbox#open(content, opts) 255 | endfunc 256 | 257 | 258 | "---------------------------------------------------------------------- 259 | " preview quickfix 260 | "---------------------------------------------------------------------- 261 | function! quickui#tools#preview_quickfix(...) 262 | if quickui#preview#visible() 263 | call quickui#preview#close() 264 | return 0 265 | endif 266 | if &bt != 'quickfix' 267 | call quickui#utils#errmsg('Not in quickfix window !') 268 | return -1 269 | endif 270 | if !exists('b:__quickui_qf__') 271 | let b:__quickui_qf__ = {} 272 | endif 273 | let obj = b:__quickui_qf__ 274 | if !has_key(obj, 'version') 275 | let obj.version = -1 276 | endif 277 | if b:changedtick != obj.version 278 | if getwininfo(win_getid())[0].loclist != 0 279 | let obj.items = getloclist(0) 280 | else 281 | let obj.items = getqflist() 282 | endif 283 | let obj.version = b:changedtick 284 | endif 285 | let index = (a:0 > 0)? a:1 : line('.') 286 | if index < 1 || index > len(obj.items) 287 | call quickui#utils#errmsg('No information in this line') 288 | return -2 289 | endif 290 | let item = obj.items[index - 1] 291 | if item.valid == 0 292 | return -3 293 | endif 294 | if item.bufnr <= 0 295 | return -4 296 | endif 297 | let name = bufname(item.bufnr) 298 | let opts = {'cursor':item.lnum} 299 | call quickui#preview#open(name, opts) 300 | " echom 'lnum:'. item.lnum 301 | endfunc 302 | 303 | 304 | "---------------------------------------------------------------------- 305 | " preview tag 306 | "---------------------------------------------------------------------- 307 | function! quickui#tools#preview_tag(tagname) 308 | let tagname = (a:tagname == '')? expand('') : a:tagname 309 | if tagname == '' 310 | call quickui#utils#errmsg('Error: empty tagname') 311 | return 0 312 | endif 313 | let obj = quickui#core#object(0) 314 | let reuse = 0 315 | if has_key(obj, 'ptag') 316 | let ptag = obj.ptag 317 | if get(ptag, 'tagname', '') == tagname 318 | let reuse = 1 319 | endif 320 | endif 321 | if reuse == 0 322 | let obj.ptag = {} 323 | let ptag = obj.ptag 324 | let ptag.taglist = quickui#tags#tagfind(tagname) 325 | let ptag.tagname = tagname 326 | let ptag.index = 0 327 | else 328 | let ptag = obj.ptag 329 | let ptag.index += 1 330 | if ptag.index >= len(ptag.taglist) 331 | let ptag.index = 0 332 | endif 333 | endif 334 | if len(ptag.taglist) == 0 335 | call quickui#utils#errmsg('E257: preview: tag not find "' . tagname . '"') 336 | return 1 337 | endif 338 | if ptag.index >= len(ptag.taglist) || ptag.index < 0 339 | let ptag.index = 0 340 | endif 341 | let taginfo = ptag.taglist[ptag.index] 342 | let filename = taginfo.filename 343 | if !filereadable(filename) 344 | call quickui#utils#errmsg('E484: Can not open file '.filename) 345 | return 2 346 | endif 347 | if !has_key(taginfo, 'line') 348 | call quickui#utils#errmsg('Error: no "line" information in your tags, regenerate with -n') 349 | return 3 350 | endif 351 | let text = '('.(ptag.index + 1).'/'.len(ptag.taglist).')' 352 | let opts = {'cursor':taginfo.line, 'title':text} 353 | call quickui#preview#open(filename, opts) 354 | let text = taginfo.name 355 | let text.= ' ('.(ptag.index + 1).'/'.len(ptag.taglist).') ' 356 | let text.= filename 357 | if has_key(taginfo, 'line') 358 | let text .= ':'.taginfo.line 359 | endif 360 | let display = has('gui_running')? 0 : 1 361 | let display = get(g:, 'quickui_preview_tag_msg', display) 362 | if display != 0 363 | call quickui#utils#print(text, 1) 364 | endif 365 | return 0 366 | endfunc 367 | 368 | 369 | "---------------------------------------------------------------------- 370 | " display vim help in popup 371 | "---------------------------------------------------------------------- 372 | function! quickui#tools#display_help(tag) 373 | if !exists('s:help_tags') 374 | let fn = expand('$VIMRUNTIME/doc/tags') 375 | if filereadable(fn) 376 | let content = readfile(fn) 377 | let s:help_tags = {} 378 | for line in content 379 | let parts = split(line, "\t") 380 | if len(parts) >= 3 381 | let s:help_tags[parts[0]] = [parts[1], parts[2]] 382 | endif 383 | endfor 384 | endif 385 | endif 386 | if !exists('s:help_tags') 387 | call quickui#utils#errmsg('Sorry, not find help tags in $VIMRUNTIME') 388 | return -1 389 | endif 390 | if !has_key(s:help_tags, a:tag) 391 | call quickui#utils#errmsg('E149: Sorry, no help for '. a:tag) 392 | return -2 393 | endif 394 | let item = s:help_tags[a:tag] 395 | let name = expand($VIMRUNTIME . '/doc/' . item[0]) 396 | let command = substitute(item[1], '\*', '', 'g') 397 | if !filereadable(name) 398 | call quickui#utils#errmsg('E484: Sorry, cannot open file '.name) 399 | return -3 400 | endif 401 | let content = readfile(name) 402 | let opts = {'syntax':'help', 'color':'QuickPreview', 'close':'button'} 403 | let opts.title = 'Help: ' . fnamemodify(name, ':t') 404 | let g:quickui#tools#hint = item[1] 405 | let opts.command = ['silent! exec g:quickui#tools#hint'] 406 | let opts.command += ["exec 'nohl'"] 407 | let opts.command += ["normal zz"] 408 | let opts.w = 80 409 | " echom opts 410 | let winid = quickui#textbox#open(content, opts) 411 | return 0 412 | endfunc 413 | 414 | 415 | 416 | "---------------------------------------------------------------------- 417 | " save curses help 418 | "---------------------------------------------------------------------- 419 | let s:previous_cursor = {} 420 | 421 | function! s:remember_cursor_context(code) 422 | let hwnd = g:quickui#context#current 423 | let name = hwnd.opts.keep_name 424 | let s:previous_cursor[name] = g:quickui#context#cursor 425 | endfunc 426 | 427 | function! s:remember_cursor_listbox(code) 428 | let hwnd = g:quickui#listbox#current 429 | let name = hwnd.opts.keep_name 430 | let s:previous_cursor[name] = g:quickui#listbox#cursor 431 | endfunc 432 | 433 | function! quickui#tools#clever_context(name, content, opts) 434 | let opts = deepcopy(a:opts) 435 | let opts.index = get(s:previous_cursor, a:name, 0) 436 | let opts.keep_name = a:name 437 | let opts.callback = function('s:remember_cursor_context') 438 | let content = quickui#context#reduce_items(a:content) 439 | call quickui#context#open_nested(content, opts) 440 | endfunc 441 | 442 | function! quickui#tools#clever_listbox(name, content, opts) 443 | let opts = deepcopy(a:opts) 444 | let opts.index = get(s:previous_cursor, a:name, 0) 445 | let opts.keep_name = a:name 446 | let opts.callback = function('s:remember_cursor_listbox') 447 | call quickui#listbox#open(a:content, opts) 448 | endfunc 449 | 450 | function! quickui#tools#clever_inputlist(name, content, opts) 451 | let opts = deepcopy(a:opts) 452 | let opts.index = get(s:previous_cursor, a:name, 0) 453 | let opts.keep_name = a:name 454 | " let opts.callback = function('s:remember_cursor_listbox') 455 | let hr = quickui#listbox#inputlist(a:content, opts) 456 | if hr >= 0 457 | let s:previous_cursor[a:name] = hr 458 | endif 459 | return hr 460 | endfunc 461 | 462 | 463 | "---------------------------------------------------------------------- 464 | " terminal 465 | "---------------------------------------------------------------------- 466 | function! quickui#tools#terminal(name) 467 | if !exists('g:quickui_terminal_tools') 468 | let g:quickui_terminal_tools = {} 469 | endif 470 | if !has_key(g:quickui_terminal_tools, a:name) 471 | call quickui#utils#errmsg('ERROR: tool ' . a:name . ' not defined !') 472 | return -1 473 | endif 474 | let tools = g:quickui_terminal_tools[a:name] 475 | if !has_key(tools, 'cmd') 476 | call quickui#utils#errmsg('ERROR: key cmd not present in tool ' . a:name) 477 | return -1 478 | endif 479 | let opts = {} 480 | let cmd = tools.cmd 481 | let w = get(g:, 'quickui_terminal_w', 80) 482 | let h = get(g:, 'quickui_terminal_h', 24) 483 | let opts.w = get(tools, 'w', w) 484 | let opts.h = get(tools, 'h', h) 485 | if has_key(tools, 'color') 486 | if tools.color != '' 487 | let opts.color = tools.color 488 | endif 489 | endif 490 | if has_key(tools, 'title') 491 | let opts.title = tools.title 492 | endif 493 | if has_key(tools, 'callback') 494 | let opts.callback = tools.callback 495 | endif 496 | if has_key(tools, 'prepare') 497 | let opts.prepare = tools.prepare 498 | endif 499 | if has_key(tools, 'cwd') 500 | let opts.cwd = tools.cwd 501 | endif 502 | if has_key(tools, 'script') 503 | let opts.safe = tools.script 504 | endif 505 | if has_key(tools, 'pause') 506 | if tools.pause 507 | let opts.pause = 1 508 | endif 509 | endif 510 | if has_key(tools, 'close') 511 | if tools.close 512 | let opts.close = 1 513 | endif 514 | endif 515 | call quickui#terminal#dialog(cmd, opts) 516 | return 0 517 | endfunc 518 | 519 | 520 | "---------------------------------------------------------------------- 521 | " search inputbox 522 | "---------------------------------------------------------------------- 523 | function! quickui#tools#input_search() 524 | let cword = expand('') 525 | let title = 'Enter text to search:' 526 | let text = quickui#input#open(title, cword, 'search') 527 | redraw 528 | if text != '' 529 | let text = escape(text, '[\/*~^.') 530 | call feedkeys("\/" . text . "\", 'n') 531 | endif 532 | endfunc 533 | 534 | 535 | 536 | -------------------------------------------------------------------------------- /autoload/quickui/window.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " window.vim - 4 | " 5 | " Created by skywind on 2021/12/08 6 | " Last Modified: 2021/12/08 23:45 7 | " 8 | "====================================================================== 9 | 10 | " vim: set ts=4 sw=4 tw=78 noet : 11 | 12 | 13 | "---------------------------------------------------------------------- 14 | " window class 15 | "---------------------------------------------------------------------- 16 | let s:window = {} 17 | let s:window.w = 1 " window width 18 | let s:window.h = 1 " window height 19 | let s:window.x = 1 " column starting from 0 20 | let s:window.y = 1 " row starting from 0 21 | let s:window.z = 40 " priority 22 | let s:window.winid = -1 " window id 23 | let s:window.dirty = 0 " need update buffer ? 24 | let s:window.text = [] " text lines 25 | let s:window.bid = -1 " allocated buffer id 26 | let s:window.hide = 0 " visibility 27 | let s:window.mode = 0 " mode: 0/created, 1/closed 28 | let s:window.opts = {} " creation options 29 | let s:window.info = {} " init environment 30 | let s:window.quit = 0 " closed by button ? (vim only) 31 | 32 | 33 | "---------------------------------------------------------------------- 34 | " internal 35 | "---------------------------------------------------------------------- 36 | let s:has_nvim = g:quickui#core#has_nvim 37 | let s:has_nvim_060 = g:quickui#core#has_nvim_060 38 | 39 | 40 | "---------------------------------------------------------------------- 41 | " prepare opts 42 | "---------------------------------------------------------------------- 43 | function! s:window.__prepare_opts(textlist, opts) 44 | let opts = deepcopy(a:opts) 45 | let opts.x = get(a:opts, 'x', 1) 46 | let opts.y = get(a:opts, 'y', 1) 47 | let opts.z = get(a:opts, 'z', 40) 48 | let opts.w = get(a:opts, 'w', 1) 49 | let opts.h = get(a:opts, 'h', -1) 50 | let opts.hide = get(a:opts, 'hide', 0) 51 | let opts.wrap = get(a:opts, 'wrap', 0) 52 | let opts.color = get(a:opts, 'color', 'QuickBG') 53 | let opts.border = get(a:opts, 'border', 0) 54 | let self.opts = opts 55 | let self.bid = quickui#core#buffer_alloc() 56 | let self.dirty = 1 57 | let self.x = opts.x 58 | let self.y = opts.y 59 | let self.z = opts.z 60 | let self.w = (opts.w < 1)? 1 : (opts.w) 61 | let self.h = (opts.h < 1)? 1 : (opts.h) 62 | let self.hide = opts.hide 63 | let self.mode = 0 64 | if has_key(a:opts, 'padding') 65 | let self.opts.padding = a:opts.padding 66 | else 67 | let self.opts.padding = [0,0,0,0] 68 | endif 69 | let pad = self.opts.padding 70 | let info = self.info 71 | let info.tw = self.w + pad[1] + pad[3] 72 | let info.th = self.h + pad[0] + pad[2] 73 | let sum_pad = pad[0] + pad[1] + pad[2] + pad[3] 74 | let info.has_padding = (sum_pad > 0)? 1 : 0 75 | let border = quickui#core#border_auto(self.opts.border) 76 | let info.has_border = (self.opts.border > 0)? 1 : 0 77 | if info.has_border != 0 78 | let info.tw += 2 79 | let info.th += 2 80 | endif 81 | " echom info 82 | call self.set_text(a:textlist) 83 | if opts.h < 0 84 | let opts.h = len(self.text) 85 | endif 86 | let cmd = [] 87 | if has_key(opts, 'tabstop') 88 | let cmd += ['setl tabstop=' . get(opts, 'tabstop', 4)] 89 | endif 90 | if has_key(opts, 'list') 91 | let cmd += [(opts.list)? 'setl list' : 'setl nolist'] 92 | else 93 | let cmd += ['setl nolist'] 94 | endif 95 | if get(opts, 'number', 0) != 0 96 | let cmd += ['setl number'] 97 | else 98 | let cmd += ['setl nonumber'] 99 | endif 100 | let cmd += ['setl scrolloff=0'] 101 | let cmd += ['setl signcolumn=no'] 102 | if has_key(opts, 'syntax') 103 | let cmd += ['set ft=' . fnameescape(opts.syntax)] 104 | endif 105 | if has_key(opts, 'cursorline') 106 | let need = (opts.cursorline)? 'cursorline' : 'nocursorlin' 107 | let cmd += ['setl ' . need] 108 | if exists('+cursorlineopt') 109 | let cmd += ['setl cursorlineopt=both'] 110 | endif 111 | else 112 | let cmd += ['setl nocursorline'] 113 | endif 114 | let cmd += ['setl nocursorcolumn nospell'] 115 | let cmd += [opts.wrap? 'setl wrap' : 'setl nowrap'] 116 | if has_key(opts, 'command') 117 | let command = opts.command 118 | if type(command) == type([]) 119 | let cmd += command 120 | else 121 | let cmd += [''. command] 122 | endif 123 | endif 124 | let info.cmd = cmd 125 | let info.pending_cmd = [] 126 | let info.border_winid = -1 127 | let info.border_bid = -1 128 | endfunc 129 | 130 | 131 | "---------------------------------------------------------------------- 132 | " win filter 133 | "---------------------------------------------------------------------- 134 | function! s:popup_filter(winid, key) 135 | let local = quickui#core#popup_local(a:winid) 136 | let hwnd = local.window_hwnd 137 | endfunc 138 | 139 | 140 | "---------------------------------------------------------------------- 141 | " exited 142 | "---------------------------------------------------------------------- 143 | function! s:popup_exit(winid, code) 144 | let local = quickui#core#popup_local(a:winid) 145 | let hwnd = local.window_hwnd 146 | call quickui#core#popup_clear(a:winid) 147 | let hwnd.quit = 1 148 | let hwnd.winid = -1 149 | endfunc 150 | 151 | 152 | "---------------------------------------------------------------------- 153 | " create window in vim 154 | "---------------------------------------------------------------------- 155 | function! s:window.__vim_create() 156 | let opts = {"hidden":1, "pos": 'topleft'} 157 | let opts.hidden = 1 158 | let opts.wrap = self.opts.wrap 159 | let opts.minwidth = self.w 160 | let opts.maxwidth = self.w 161 | let opts.minheight = self.h 162 | let opts.maxheight = self.h 163 | let opts.col = self.x + 1 164 | let opts.line = self.y + 1 165 | let opts.mapping = 0 166 | let opts.fixed = (opts.wrap == 0)? 1 : 0 167 | let opts.cursorline = get(self.opts, 'cursorline', 0) 168 | let opts.drag = get(self.opts, 'drag', 0) 169 | let opts.scrollbar = 0 170 | let opts.zindex = self.z + 1 171 | if get(self.opts, 'button', 0) != 0 172 | let opts.close = 'button' 173 | endif 174 | let self.winid = popup_create(self.bid, opts) 175 | let winid = self.winid 176 | let local = quickui#core#popup_local(winid) 177 | let local.window_hwnd = self 178 | let init = [] 179 | let init += ['setlocal nonumber signcolumn=no scrolloff=0'] 180 | call quickui#core#win_execute(winid, init, 1) 181 | let opts = {} 182 | let opts.filter = function('s:popup_filter') 183 | let opts.callback = function('s:popup_exit') 184 | let opts.highlight = self.opts.color 185 | let border = quickui#core#border_auto(self.opts.border) 186 | if self.info.has_border 187 | let opts.borderchars = border 188 | let opts.border = [1,1,1,1,1,1,1,1,1] 189 | let bc = get(self.opts, 'bordercolor', 'QuickBorder') 190 | let opts.borderhighlight = [bc, bc, bc, bc] 191 | if has_key(self.opts, 'title') 192 | let opts.title = self.opts.title 193 | endif 194 | endif 195 | if has_key(self.opts, 'padding') 196 | let opts.padding = self.opts.padding 197 | endif 198 | call setwinvar(winid, '&wincolor', self.opts.color) 199 | call popup_setoptions(winid, opts) 200 | call quickui#core#win_execute(winid, self.info.cmd) 201 | let pc = self.info.pending_cmd 202 | if len(pc) > 0 203 | call quickui#core#win_execute(winid, pc) 204 | let self.info.pending_cmd = [] 205 | endif 206 | let self.mode = 1 207 | if get(self.opts, 'center', 0) != 0 208 | call self.center() 209 | endif 210 | if self.hide == 0 211 | call popup_show(winid) 212 | endif 213 | endfunc 214 | 215 | 216 | "---------------------------------------------------------------------- 217 | " create window in nvim 218 | "---------------------------------------------------------------------- 219 | function! s:window.__nvim_create() 220 | let opts = {'focusable':0, 'style':'minimal', 'relative':'editor'} 221 | let opts.row = self.y 222 | let opts.col = self.x 223 | let opts.width = self.w 224 | let opts.height = self.h 225 | let opts.focusable = get(self.opts, 'focusable', 0) 226 | if s:has_nvim_060 227 | let opts.noautocmd = 1 228 | let opts.zindex = self.z + 1 229 | endif 230 | let info = self.info 231 | let info.nvim_opts = opts 232 | let info.sim_border = 0 233 | let info.off_x = 0 234 | let info.off_y = 0 235 | let pad = self.opts.padding 236 | if info.has_border 237 | let info.sim_border = 1 238 | let info.off_x = 1 239 | let info.off_y = 1 240 | if info.has_padding 241 | let info.sim_border = 1 242 | let info.off_x += pad[3] 243 | let info.off_y += pad[0] 244 | endif 245 | endif 246 | if info.has_border 247 | let tw = info.tw 248 | let th = info.th 249 | let opts.col += info.off_x 250 | let opts.row += info.off_y 251 | let t = get(self.opts, 'title', '') 252 | let b = get(self.opts, 'button', 0) 253 | let border = self.opts.border 254 | let back = quickui#utils#make_border(tw - 2, th - 2, border, t, b) 255 | let info.border_bid = quickui#core#buffer_alloc() 256 | call quickui#core#buffer_update(info.border_bid, back) 257 | let op = {'relative':'editor', 'focusable':0, 'style':'minimal'} 258 | let op.focusable = get(self.opts, 'focusable', 0) 259 | let op.width = tw 260 | let op.height = th 261 | let op.col = self.x 262 | let op.row = self.y 263 | if s:has_nvim_060 264 | let op.noautocmd = 1 265 | let op.zindex = self.z 266 | endif 267 | let info.border_opts = op 268 | let init = [] 269 | let init += ['setl tabstop=' . get(self.opts, 'tabstop', 4)] 270 | let init += ['setl signcolumn=no scrolloff=0 nowrap nonumber'] 271 | let init += ['setl nocursorline nolist'] 272 | if exists('+cursorlineopt') 273 | let init += ['setl cursorlineopt=both'] 274 | endif 275 | let info.border_init = init 276 | endif 277 | let self.mode = 1 278 | if get(self.opts, 'center', 0) != 0 279 | call self.center() 280 | endif 281 | if self.hide == 0 282 | call self.__nvim_show() 283 | endif 284 | endfunc 285 | 286 | 287 | "---------------------------------------------------------------------- 288 | " nvim - show window 289 | "---------------------------------------------------------------------- 290 | function! s:window.__nvim_show() 291 | if self.mode == 0 292 | return 293 | elseif self.winid >= 0 294 | return 295 | endif 296 | call self.move(self.x, self.y) 297 | let info = self.info 298 | let winid = nvim_open_win(self.bid, 0, info.nvim_opts) 299 | let self.winid = winid 300 | let color = self.opts.color 301 | call quickui#core#win_execute(winid, info.cmd) 302 | if len(info.pending_cmd) > 0 303 | call quickui#core#win_execute(winid, info.pending_cmd) 304 | let info.pending_cmd = [] 305 | endif 306 | call nvim_win_set_option(self.winid, 'winhl', 'Normal:'. color) 307 | if info.has_border 308 | let bwid = nvim_open_win(info.border_bid, 0, info.border_opts) 309 | let info.border_winid = bwid 310 | call quickui#core#win_execute(bwid, info.border_init) 311 | call nvim_win_set_option(bwid, 'winhl', 'Normal:'. color) 312 | endif 313 | let self.hide = 0 314 | endfunc 315 | 316 | 317 | "---------------------------------------------------------------------- 318 | " nvim - hide window 319 | "---------------------------------------------------------------------- 320 | function! s:window.__nvim_hide() 321 | if self.mode == 0 322 | return 323 | elseif self.winid < 0 324 | return 325 | endif 326 | let info = self.info 327 | if info.border_winid >= 0 328 | call nvim_win_close(info.border_winid, 1) 329 | let info.border_winid = -1 330 | endif 331 | if self.winid >= 0 332 | call nvim_win_close(self.winid, 1) 333 | let self.winid = -1 334 | endif 335 | let self.hide = 1 336 | endfunc 337 | 338 | 339 | "---------------------------------------------------------------------- 340 | " open window 341 | "---------------------------------------------------------------------- 342 | function! s:window.open(textlist, opts) 343 | call self.close() 344 | call self.__prepare_opts(a:textlist, a:opts) 345 | if s:has_nvim == 0 346 | call self.__vim_create() 347 | else 348 | call self.__nvim_create() 349 | endif 350 | let self.mode = 1 351 | endfunc 352 | 353 | 354 | 355 | "---------------------------------------------------------------------- 356 | " close window 357 | "---------------------------------------------------------------------- 358 | function! s:window.close() 359 | if self.winid >= 0 360 | if s:has_nvim == 0 361 | call popup_close(self.winid) 362 | else 363 | call nvim_win_close(self.winid, 1) 364 | if self.info.border_winid >= 0 365 | call nvim_win_close(self.info.border_winid, 1) 366 | let self.info.border_winid = -1 367 | endif 368 | endif 369 | endif 370 | let self.winid = -1 371 | if self.bid >= 0 372 | call quickui#core#buffer_free(self.bid) 373 | let self.bid = -1 374 | endif 375 | if has_key(self.info, 'border_bid') 376 | if self.info.border_bid >= 0 377 | call quickui#core#buffer_free(self.info.border_bid) 378 | let self.info.border_bid = -1 379 | endif 380 | endif 381 | let self.hide = 0 382 | let self.mode = 0 383 | endfunc 384 | 385 | 386 | "---------------------------------------------------------------------- 387 | " show the window 388 | "---------------------------------------------------------------------- 389 | function! s:window.show(show) 390 | if self.mode == 0 391 | return 392 | elseif s:has_nvim == 0 393 | if a:show == 0 394 | if self.winid >= 0 395 | call popup_hide(self.winid) 396 | endif 397 | else 398 | if self.winid >= 0 399 | call popup_show(self.winid) 400 | endif 401 | endif 402 | else 403 | if a:show == 0 404 | call self.__nvim_hide() 405 | else 406 | call self.__nvim_show() 407 | endif 408 | endif 409 | let self.hide = (a:show == 0)? 1 : 0 410 | endfunc 411 | 412 | 413 | "---------------------------------------------------------------------- 414 | " move window 415 | "---------------------------------------------------------------------- 416 | function! s:window.__move(x, y) 417 | let self.x = a:x 418 | let self.y = a:y 419 | if self.mode == 0 420 | return 421 | elseif s:has_nvim == 0 422 | if self.winid >= 0 423 | let opts = {} 424 | let opts.col = self.x + 1 425 | let opts.line = self.y + 1 426 | call popup_move(self.winid, opts) 427 | endif 428 | else 429 | let info = self.info 430 | let opts = info.nvim_opts 431 | let opts.col = self.x + info.off_x 432 | let opts.row = self.y + info.off_y 433 | if info.has_border != 0 434 | let opts = info.border_opts 435 | let opts.col = self.x 436 | let opts.row = self.y 437 | endif 438 | if self.winid >= 0 439 | let op = {'relative':'editor'} 440 | let op.col = info.nvim_opts.col 441 | let op.row = info.nvim_opts.row 442 | call nvim_win_set_config(self.winid, op) 443 | endif 444 | if info.has_border != 0 445 | if info.border_winid >= 0 446 | let op = {'relative':'editor'} 447 | let op.col = info.border_opts.col 448 | let op.row = info.border_opts.row 449 | call nvim_win_set_config(info.border_winid, op) 450 | endif 451 | endif 452 | endif 453 | endfunc 454 | 455 | 456 | "---------------------------------------------------------------------- 457 | " actual move 458 | "---------------------------------------------------------------------- 459 | function! s:window.move(x, y) 460 | let x = a:x 461 | let y = a:y 462 | let w = self.info.tw 463 | let h = self.info.th 464 | let sw = &columns 465 | let sh = &lines 466 | let x = (x + w > sw)? (sw - w) : x 467 | let y = (y + h > sh)? (sh - h) : y 468 | let x = (x < 0)? 0 : x 469 | let y = (y < 0)? 0 : y 470 | " unsilent echom ['move', x, a:x, self.opts.x] 471 | call self.__move(x, y) 472 | endfunc 473 | 474 | 475 | "---------------------------------------------------------------------- 476 | " center window 477 | "---------------------------------------------------------------------- 478 | function! s:window.center(...) 479 | let w = self.w 480 | let h = self.h 481 | let style = (a:0 < 1)? 0 : (a:1) 482 | if self.mode != 0 483 | let w = self.info.tw 484 | let h = self.info.th 485 | endif 486 | let x = (&columns - w) / 2 487 | if style == 0 488 | let height = &lines - &cmdheight - 1 489 | let middle = height * 38 / 100 490 | let y = middle - (h + 1) / 2 491 | let y = (y < 0)? 0 : y 492 | else 493 | let y = (&lines - h) / 2 494 | let limit1 = (&lines - 2) * 80 / 100 495 | let limit2 = (&lines - 2) 496 | if h + 8 < limit1 497 | let y = (limit1 - h) / 2 498 | else 499 | let y = (limit2 - h) / 2 500 | endif 501 | endif 502 | call self.move(x, y) 503 | endfunc 504 | 505 | 506 | "---------------------------------------------------------------------- 507 | " resize 508 | "---------------------------------------------------------------------- 509 | function! s:window.resize(w, h) 510 | let self.w = a:w 511 | let self.h = a:h 512 | let info = self.info 513 | if self.mode == 0 514 | let info.tw = self.w 515 | let info.th = self.h 516 | return 517 | endif 518 | let pad = self.opts.padding 519 | let info.tw = self.w + pad[1] + pad[3] 520 | let info.th = self.h + pad[0] + pad[2] 521 | let info.tw += (info.has_border? 2 : 0) 522 | let info.th += (info.has_border? 2 : 0) 523 | if self.winid < 0 524 | return 525 | endif 526 | if s:has_nvim == 0 527 | let opts = {} 528 | let opts.minwidth = self.w 529 | let opts.maxwidth = self.w 530 | let opts.minheight = self.h 531 | let opts.maxheight = self.h 532 | call popup_move(self.winid, opts) 533 | else 534 | let opts = info.nvim_opts 535 | let opts.width = self.w 536 | let opts.height = self.h 537 | if info.has_border 538 | let opts = info.border_opts 539 | let opts.width = info.tw 540 | let opts.height = info.th 541 | let t = get(self.opts, 'title', '') 542 | let b = self.opts.border 543 | let tw = info.tw 544 | let th = info.th 545 | let btn = get(self.opts, 'button', 0) 546 | let back = quickui#utils#make_border(tw - 2, th - 2, b, t, btn) 547 | call quickui#core#buffer_update(info.border_bid, back) 548 | endif 549 | if self.winid >= 0 550 | let op = {'width':self.w, 'height':self.h} 551 | call nvim_win_set_config(self.winid, op) 552 | if info.has_border 553 | if info.border_winid >= 0 554 | let op = {'width':info.tw, 'height':info.th} 555 | call nvim_win_set_config(info.border_winid, op) 556 | endif 557 | endif 558 | endif 559 | endif 560 | endfunc 561 | 562 | 563 | "---------------------------------------------------------------------- 564 | " execute commands 565 | "---------------------------------------------------------------------- 566 | function! s:window.execute(cmdlist) 567 | if type(a:cmdlist) == v:t_string 568 | let cmd = split(a:cmdlist, '\n') 569 | else 570 | let cmd = a:cmdlist 571 | endif 572 | let winid = self.winid 573 | if winid >= 0 574 | let pc = self.info.pending_cmd 575 | if len(pc) > 0 576 | call quickui#core#win_execute(winid, pc) 577 | let self.info.pending_cmd = [] 578 | endif 579 | if len(cmd) > 0 580 | call quickui#core#win_execute(winid, cmd) 581 | endif 582 | else 583 | if !has_key(self.info, 'pending_cmd') 584 | let self.info.pending_cmd = cmd 585 | else 586 | let self.info.pending_cmd += cmd 587 | endif 588 | endif 589 | endfunc 590 | 591 | 592 | "---------------------------------------------------------------------- 593 | " update text in buffer 594 | "---------------------------------------------------------------------- 595 | function! s:window.update() 596 | if self.bid >= 0 597 | call quickui#core#buffer_update(self.bid, self.text) 598 | endif 599 | endfunc 600 | 601 | 602 | "---------------------------------------------------------------------- 603 | " set content 604 | "---------------------------------------------------------------------- 605 | function! s:window.set_text(textlist) 606 | if type(a:textlist) == v:t_list 607 | let textlist = deepcopy(a:textlist) 608 | else 609 | let textlist = split(a:textlist, '\n', 1) 610 | endif 611 | let self.text = textlist 612 | call self.update() 613 | endfunc 614 | 615 | 616 | "---------------------------------------------------------------------- 617 | " set line 618 | "---------------------------------------------------------------------- 619 | function! s:window.set_line(index, text, ...) 620 | let require = a:index + 1 621 | let refresh = (a:0 < 1)? 1 : (a:1) 622 | let index = a:index 623 | let update = 0 624 | if index < 0 625 | return 626 | elseif len(self.text) < require 627 | let self.text += repeat([''], require - len(self.text)) 628 | let update = 1 629 | endif 630 | let self.text[a:index] = a:text 631 | if update != 0 632 | call self.update() 633 | elseif refresh != 0 634 | let bid = self.bid 635 | if bid >= 0 636 | call setbufvar(bid, '&modifiable', 1) 637 | call setbufline(bid, index + 1, [a:text]) 638 | call setbufvar(bid, '&modified', 0) 639 | endif 640 | endif 641 | endfunc 642 | 643 | 644 | "---------------------------------------------------------------------- 645 | " get line 646 | "---------------------------------------------------------------------- 647 | function! s:window.get_line(index) 648 | if a:index >= len(self.text) 649 | return '' 650 | endif 651 | return self.text[a:index] 652 | endfunc 653 | 654 | 655 | "---------------------------------------------------------------------- 656 | " syntax begin 657 | "---------------------------------------------------------------------- 658 | function! s:window.syntax_begin(...) 659 | let info = self.info 660 | let info.syntax_cmd = ['syn clear'] 661 | let info.syntax_mod = (a:0 < 1)? 1 : (a:1) 662 | endfunc 663 | 664 | 665 | "---------------------------------------------------------------------- 666 | " flush commands 667 | "---------------------------------------------------------------------- 668 | function! s:window.syntax_end() 669 | let info = self.info 670 | if has_key(info, 'syntax_cmd') != 0 671 | if len(info.syntax_cmd) > 0 672 | call self.execute(info.syntax_cmd) 673 | let info.syntax_cmd = [] 674 | endif 675 | endif 676 | endfunc 677 | 678 | 679 | "---------------------------------------------------------------------- 680 | " calculate region 681 | "---------------------------------------------------------------------- 682 | function! s:window.syntax_region(color, x1, y1, x2, y2) 683 | let info = self.info 684 | if a:y1 == a:y2 && a:x1 >= a:x2 685 | return 686 | elseif has_key(info, 'syntax_cmd') != 0 687 | let x1 = a:x1 + 1 688 | let y1 = a:y1 + 1 689 | let x2 = a:x2 + 1 690 | let y2 = a:y2 + 1 691 | let cc = a:color 692 | let mm = info.syntax_mod 693 | let cmd = quickui#core#high_region(cc, y1, x1, y2, x2, mm) 694 | let info.syntax_cmd += [cmd] 695 | " echom cmd 696 | endif 697 | endfunc 698 | 699 | 700 | "---------------------------------------------------------------------- 701 | " click window 702 | "---------------------------------------------------------------------- 703 | function! s:window.mouse_click() 704 | let winid = self.winid 705 | let retval = {'x':-1, 'y':-1} 706 | if g:quickui#core#has_nvim == 0 707 | let pos = getmousepos() 708 | if pos.winid != winid 709 | return retval 710 | endif 711 | if self.info.has_border == 0 712 | let retval.x = pos.column - 1 713 | let retval.y = pos.line - 1 714 | else 715 | let retval.x = pos.column - 2 716 | let retval.y = pos.line - 2 717 | endif 718 | else 719 | if v:mouse_winid != winid 720 | return retval 721 | endif 722 | if self.info.has_border == 0 723 | let retval.x = v:mouse_col - 1 724 | let retval.y = v:mouse_lnum - 1 725 | else 726 | let retval.x = v:mouse_col - 2 727 | let retval.y = v:mouse_lnum - 2 728 | endif 729 | endif 730 | return retval 731 | endfunc 732 | 733 | 734 | "---------------------------------------------------------------------- 735 | " refresh redraw 736 | "---------------------------------------------------------------------- 737 | function! s:window.refresh() 738 | let winid = self.winid 739 | if g:quickui#core#has_nvim == 0 740 | if winid >= 0 741 | call popup_setoptions(winid, {}) 742 | endif 743 | else 744 | endif 745 | redraw 746 | endfunc 747 | 748 | 749 | "---------------------------------------------------------------------- 750 | " constructor 751 | "---------------------------------------------------------------------- 752 | function! quickui#window#new() 753 | let obj = deepcopy(s:window) 754 | return obj 755 | endfunc 756 | 757 | 758 | -------------------------------------------------------------------------------- /colors/quickui/borland.vim: -------------------------------------------------------------------------------- 1 | 2 | hi! QuickDefaultBackground ctermfg=0 ctermbg=7 guifg=black guibg=#c0c0c0 3 | hi! QuickDefaultSel cterm=bold ctermfg=0 ctermbg=2 gui=bold guibg=brown guifg=#c0c0c0 4 | hi! QuickDefaultKey term=bold ctermfg=9 gui=bold guifg=#f92772 5 | hi! QuickDefaultDisable ctermfg=8 guifg=#75715e 6 | hi! QuickDefaultHelp ctermfg=8 guifg=#959173 7 | hi! QuickDefaultBorder ctermfg=0 ctermbg=7 guifg=black guibg=#c0c0c0 8 | hi! QuickDefaultTermBorder ctermfg=0 ctermbg=7 guifg=black guibg=#c0c0c0 9 | 10 | if &background == 'dark' 11 | hi! QuickDefaultPreview ctermbg=237 guibg=#4c4846 12 | else 13 | hi! QuickDefaultPreview ctermbg=12 guibg=#dddddd 14 | endif 15 | 16 | hi! QuickDefaultInput ctermfg=7 ctermbg=4 guifg=#e4e4e4 guibg=#0000a0 17 | hi! QuickDefaultCursor ctermfg=4 ctermbg=7 guifg=#0000a0 guibg=#e4e4e4 18 | hi! QuickDefaultVisual ctermfg=4 ctermbg=15 guifg=#0000a0 guibg=#f4f4f4 19 | 20 | -------------------------------------------------------------------------------- /colors/quickui/default.vim: -------------------------------------------------------------------------------- 1 | 2 | hi! QuickDefaultBackground ctermfg=0 ctermbg=7 guifg=black guibg=#c0c0c0 3 | hi! QuickDefaultSel cterm=bold ctermfg=0 ctermbg=2 gui=bold guibg=brown guifg=#c0c0c0 4 | hi! QuickDefaultKey term=bold ctermfg=1 gui=bold guifg=#f92772 5 | hi! QuickDefaultDisable ctermfg=6 guifg=#75715e 6 | hi! QuickDefaultHelp ctermfg=6 guifg=#959173 7 | hi! QuickDefaultBorder ctermfg=0 ctermbg=7 guifg=black guibg=#c0c0c0 8 | hi! QuickDefaultTermBorder ctermfg=0 ctermbg=7 guifg=black guibg=#c0c0c0 9 | 10 | if &background == 'dark' 11 | hi! QuickDefaultPreview ctermbg=7 guibg=#4c4846 12 | else 13 | hi! QuickDefaultPreview ctermbg=4 guibg=#dddddd 14 | endif 15 | 16 | hi! QuickDefaultInput ctermfg=7 ctermbg=4 guifg=#e4e4e4 guibg=#0000a0 17 | hi! QuickDefaultCursor ctermfg=4 ctermbg=7 guifg=#0000a0 guibg=#e4e4e4 18 | hi! QuickDefaultVisual ctermfg=4 ctermbg=6 guifg=#0000a0 guibg=#f4f4f4 19 | 20 | -------------------------------------------------------------------------------- /colors/quickui/gruvbox.vim: -------------------------------------------------------------------------------- 1 | 2 | hi! QuickDefaultBackground ctermfg=187 ctermbg=239 guifg=#ebdbb2 guibg=#504945 3 | hi! QuickDefaultSel cterm=bold ctermfg=239 ctermbg=108 gui=bold guifg=#504945 guibg=#83a598 4 | hi! QuickDefaultKey term=bold ctermfg=208 guifg=#fd9720 5 | hi! QuickDefaultDisable ctermfg=245 guifg=#928374 6 | hi! QuickDefaultHelp ctermfg=109 guifg=#83a598 7 | hi! QuickDefaultBorder ctermfg=187 ctermbg=239 guifg=#ebdbb2 guibg=#504945 8 | hi! QuickDefaultTermBorder ctermfg=187 ctermbg=239 guifg=#ebdbb2 guibg=#504945 9 | 10 | if &background == 'dark' 11 | hi! QuickDefaultPreview ctermbg=237 guibg=#4c4846 12 | else 13 | hi! QuickDefaultPreview ctermbg=12 guibg=#dddddd 14 | endif 15 | 16 | hi! QuickDefaultInput ctermfg=233 ctermbg=235 guifg=#ebdbb2 guibg=#282828 17 | hi! QuickDefaultCursor ctermfg=235 ctermbg=233 guifg=#282828 guibg=#ebdbb2 18 | hi! QuickDefaultVisual ctermfg=241 ctermbg=233 guifg=#665c54 guibg=#ebdbb2 19 | 20 | -------------------------------------------------------------------------------- /colors/quickui/papercol_dark.vim: -------------------------------------------------------------------------------- 1 | 2 | hi! QuickDefaultBackground ctermfg=251 ctermbg=236 guifg=#c6c6c6 guibg=#303030 3 | hi! QuickDefaultSel ctermfg=236 ctermbg=251 guifg=#303030 guibg=#c6c6c6 4 | hi! QuickDefaultKey term=bold ctermfg=179 gui=bold guifg=#d7af5f 5 | hi! QuickDefaultDisable ctermfg=11 guifg=#808080 6 | hi! QuickDefaultHelp ctermfg=7 ctermbg=8 guifg=#585858 guibg=#1c1c1c 7 | hi! QuickDefaultBorder ctermfg=66 ctermbg=236 guifg=#5f8787 guibg=#303030 8 | hi! QuickDefaultTermBorder ctermfg=66 ctermbg=236 guifg=#5f8787 guibg=#303030 9 | 10 | if &background == 'dark' 11 | hi! QuickDefaultPreview ctermbg=237 guibg=#4c4846 12 | else 13 | hi! QuickDefaultPreview ctermbg=12 guibg=#dddddd 14 | endif 15 | 16 | hi! QuickDefaultInput ctermfg=252 ctermbg=234 guifg=#d0d0d0 guibg=#1c1c1c 17 | hi! QuickDefaultCursor ctermfg=234 ctermbg=252 guifg=#1c1c1c guibg=#d0d0d0 18 | hi! QuickDefaultVisual ctermfg=8 ctermbg=255 guifg=#000000 guibg=#8787af 19 | 20 | -------------------------------------------------------------------------------- /colors/quickui/papercol_light.vim: -------------------------------------------------------------------------------- 1 | 2 | hi! QuickDefaultBackground ctermfg=238 ctermbg=252 guifg=#444444 guibg=#d0d0d0 3 | hi! QuickDefaultSel ctermfg=252 ctermbg=238 guifg=#d0d0d0 guibg=#444444 4 | hi! QuickDefaultKey term=bold ctermfg=162 gui=bold guifg=#d70087 5 | hi! QuickDefaultDisable term=bold ctermfg=1 guifg=#878787 6 | " hi! QuickDefaultHelp ctermfg=7 ctermbg=8 guifg=#b2b2b2 guibg=#eeeeee 7 | hi! QuickDefaultHelp ctermfg=247 guifg=#959173 8 | " hi! QuickDefaultBorder ctermfg=31 ctermbg=252 guifg=#0087af guibg=#d0d0d0 9 | " hi! QuickDefaultBorder ctermfg=31 ctermbg=252 guifg=#222222 guibg=#d0d0d0 10 | hi! QuickDefaultBorder ctermfg=24 ctermbg=252 guifg=#005f87 guibg=#d0d0d0 11 | " hi! QuickDefaultBorder ctermfg=24 ctermbg=252 guifg=#d70087 guibg=#d0d0d0 12 | " hi! QuickDefaultTermBorder ctermfg=24 ctermbg=252 guifg=#005f87 guibg=#d0d0d0 13 | hi! QuickDefaultTermBorder ctermfg=51 guifg=cyan 14 | 15 | if &background == 'dark' 16 | hi! QuickDefaultPreview ctermbg=237 guibg=#4c4846 17 | else 18 | hi! QuickDefaultPreview ctermbg=12 guibg=#dddddd 19 | endif 20 | 21 | hi! QuickDefaultMatch0 ctermfg=166 guifg=#d75f00 22 | hi! QuickDefaultMatch1 ctermfg=31 guifg=#0087af 23 | hi! QuickDefaultMatch2 ctermfg=25 guifg=#005faf 24 | hi! QuickDefaultMatch3 ctermfg=64 guifg=#5f8700 25 | hi! QuickDefaultMatch4 ctermfg=91 guifg=#8700af 26 | hi! QuickDefaultMatch5 ctermfg=247 guifg=#a2a2a2 27 | 28 | hi! QuickDefaultInput ctermfg=254 ctermbg=24 guifg=#e4e4e4 guibg=#005f87 29 | hi! QuickDefaultCursor ctermfg=238 ctermbg=222 guifg=#444444 guibg=#ffd787 30 | hi! QuickDefaultVisual ctermfg=31 ctermbg=255 guifg=#0087af guibg=#eeeeee 31 | 32 | 33 | -------------------------------------------------------------------------------- /colors/quickui/solarized.vim: -------------------------------------------------------------------------------- 1 | 2 | hi! QuickDefaultBackground ctermfg=235 ctermbg=246 guifg=#073642 guibg=#839496 3 | hi! QuickDefaultSel ctermfg=254 ctermbg=241 guifg=#eee8d5 guibg=#586e75 4 | hi! QuickDefaultKey ctermfg=166 guifg=#cb4b16 5 | hi! QuickDefaultDisable ctermfg=242 guifg=#586e75 6 | hi! QuickDefaultHelp ctermfg=32 guifg=#268bd2 7 | hi! QuickDefaultBorder ctermfg=235 ctermbg=246 guifg=#073642 guibg=#839496 8 | hi! QuickDefaultTermBorder ctermfg=235 ctermbg=246 guifg=#073642 guibg=#839496 9 | 10 | if &background == 'dark' 11 | hi! QuickDefaultPreview ctermbg=237 guibg=#4c4846 12 | else 13 | hi! QuickDefaultPreview ctermbg=12 guibg=#dddddd 14 | endif 15 | 16 | hi! QuickDefaultInput ctermfg=244 ctermbg=234 guifg=#839496 guibg=#002b36 17 | hi! QuickDefaultCursor ctermfg=234 ctermbg=234 guifg=#002b36 guibg=#839496 18 | hi! QuickDefaultVisual ctermfg=234 ctermbg=239 guifg=#002b36 guibg=DarkGray 19 | 20 | -------------------------------------------------------------------------------- /colors/quickui/system.vim: -------------------------------------------------------------------------------- 1 | 2 | hi! link QuickDefaultBackground Pmenu 3 | hi! link QuickDefaultSel PmenuSel 4 | hi! link QuickDefaultKey Title 5 | hi! link QuickDefaultDisable Comment 6 | hi! link QuickDefaultHelp Conceal 7 | hi! link QuickDefaultBorder Pmenu 8 | hi! link QuickDefaultTermBorder Pmenu 9 | 10 | if &background == 'dark' 11 | hi! QuickDefaultPreview ctermbg=237 guibg=#4c4846 12 | else 13 | hi! QuickDefaultPreview ctermbg=12 guibg=#dddddd 14 | endif 15 | 16 | 17 | hi! link QuickDefaultInput NonText 18 | hi! link QuickDefaultCursor Cursor 19 | hi! link QuickDefaultVisual Visual 20 | 21 | 22 | -------------------------------------------------------------------------------- /plugin/quickui.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " quickui.vim - 4 | " 5 | " Created by skywind on 2019/12/26 6 | " Last Modified: 2021/12/08 23:01 7 | " 8 | "====================================================================== 9 | 10 | " vim: set noet fenc=utf-8 ff=unix sts=4 sw=4 ts=4 : 11 | 12 | 13 | " require vim 8.2+ 14 | if has('patch-8.2.1') == 0 || has('nvim') 15 | " finish 16 | endif 17 | 18 | 19 | "---------------------------------------------------------------------- 20 | " exports 21 | "---------------------------------------------------------------------- 22 | let g:quickui_version = '1.4.3' 23 | 24 | 25 | "---------------------------------------------------------------------- 26 | " internals 27 | "---------------------------------------------------------------------- 28 | let s:home = fnamemodify(resolve(expand(':p')), ':h') 29 | let s:rtp = fnamemodify(s:home, ':h') 30 | 31 | 32 | "---------------------------------------------------------------------- 33 | " QuickUI command 34 | "---------------------------------------------------------------------- 35 | command! -bang -nargs=* -complete=customlist,quickui#command#complete 36 | \ QuickUI call quickui#command#run('', ) 37 | 38 | 39 | "---------------------------------------------------------------------- 40 | " setup variables 41 | "---------------------------------------------------------------------- 42 | if exists('g:quickui_border_style') 43 | let g:quickui#style#border = get(g:, 'quickui_border_style', 1) 44 | endif 45 | 46 | function! s:set_quickui_hi() 47 | " hi! QuickDefaultSel ctermbg= 48 | hi! link QuickBG QuickDefaultBackground 49 | hi! link QuickSel QuickDefaultSel 50 | hi! link QuickKey QuickDefaultKey 51 | hi! link QuickOff QuickDefaultDisable 52 | hi! link QuickHelp QuickDefaultHelp 53 | hi! link QuickBorder QuickDefaultBorder 54 | hi! link QuickTermBorder QuickDefaultTermBorder 55 | hi! link QuickPreview QuickDefaultPreview 56 | 57 | " for input box 58 | hi! link QuickInput QuickDefaultInput 59 | hi! link QuickCursor QuickDefaultCursor 60 | hi! link QuickVisual QuickDefaultVisual 61 | endfunc 62 | 63 | function! QuickThemeChange(theme) 64 | let theme = 'default' 65 | if a:theme == '' 66 | let theme = 'default' 67 | elseif a:theme == 'default' || a:theme == 'ansi' 68 | let theme = 'default' 69 | elseif a:theme == 'borland' || a:theme == 'turboc' 70 | let theme = 'borland' 71 | elseif a:theme == 'colorscheme' || a:theme == 'system' || a:theme == 'vim' 72 | let theme = 'system' 73 | elseif a:theme == 'gruvbox' 74 | let theme = 'gruvbox' 75 | elseif a:theme == 'solarized' 76 | let theme = 'solarized' 77 | elseif a:theme == 'papercol' || a:theme == 'papercol-dark' 78 | let theme = 'papercol_dark' 79 | elseif a:theme == 'papercol dark' 80 | let theme = 'papercol_dark' 81 | elseif a:theme == 'papercol-light' || a:theme == 'papercol light' 82 | let theme = 'papercol_light' 83 | else 84 | let theme = a:theme 85 | endif 86 | let s:fname = s:rtp . '/colors/quickui/' . theme . '.vim' 87 | if !filereadable(s:fname) 88 | let s:fname = s:rtp . '/colors/quickui/borland.vim' 89 | endif 90 | if filereadable(s:fname) 91 | exec "source " . fnameescape(s:fname) 92 | endif 93 | call s:set_quickui_hi() 94 | endfunc 95 | 96 | let s:scheme = get(g:, 'quickui_color_scheme', '') 97 | call QuickThemeChange(s:scheme) 98 | 99 | augroup quickui "{{{ 100 | autocmd! 101 | autocmd Colorscheme * call QuickThemeChange(get(g:, 'quickui_color_scheme', '')) 102 | augroup END "}}} 103 | 104 | call s:set_quickui_hi() 105 | 106 | 107 | -------------------------------------------------------------------------------- /test/demo_menu.vim: -------------------------------------------------------------------------------- 1 | 2 | if has('patch-8.2.1') == 0 || has('nvim') 3 | finish 4 | endif 5 | 6 | call quickui#menu#reset() 7 | 8 | " install a 'File' menu, each item comprises its name and command to execute 9 | call quickui#menu#install('&File', [ 10 | \ [ "&New File\tCtrl+n", 'new' ], 11 | \ [ "&Open File\t(F3)", 'call feedkeys(":edit ")' ], 12 | \ [ "&Close", 'close' ], 13 | \ [ "--", '' ], 14 | \ [ "&Save\tCtrl+s", 'w'], 15 | \ [ "Save &As", 'call feedkey(":saveas ")' ], 16 | \ [ "Save All", 'wa' ], 17 | \ [ "--", '' ], 18 | \ [ "E&xit\tAlt+x", 'q' ], 19 | \ ]) 20 | 21 | " items contains tips, tips will display in the bottom of screen 22 | call quickui#menu#install('&Plugin', [ 23 | \ ["&NERDTree\ttn", 'NERDTreeToggle', 'toggle nerdtree'], 24 | \ ['&Tagbar', '', 'toggle tagbar'], 25 | \ ["&Choose Window/Tab\tAlt+e", "ChooseWin", "fast switch win/tab with vim-choosewin"], 26 | \ ["-"], 27 | \ ["&Browse in github", "Gbrowse", "using tpope's rhubarb to open browse and view the file"], 28 | \ ["&Startify", "Startify", "using tpope's rhubarb to open browse and view the file"], 29 | \ ["&Gist", "Gist", "open gist with mattn/gist-vim"], 30 | \ ["&Edit Note", "Note", "edit note with vim-notes"], 31 | \ ["&Display Calendar", "Calendar", "display a calender"], 32 | \ ["-"], 33 | \ ["Plugin &List", "PlugList", 'list available plugins'], 34 | \ ["Plugin &Update", "PlugUpdate", 'update plugins'], 35 | \ ]) 36 | 37 | " script inside %{...} will be evaluated and expanded in the string 38 | call quickui#menu#install("&Tools", [ 39 | \ ["Switch &Buffer", 'call quickui#tools#kit_buffers("e")'], 40 | \ ["-"], 41 | \ ['Set &Spell %{&spell? "Off":"On"}', 'set spell!', 'Toggle spell check %{&spell? "off" : "on"}'], 42 | \ ['Set &Cursor Line %{&cursorline? "Off":"On"}', 'set cursorline!', 'Toggle cursor line %{&cursorline? "off" : "on"}'], 43 | \ ['Set &Paste %{&paste? "Off":"On"}', 'set paste!', 'Toggle paste mode %{&paste? "off" : "on"}'], 44 | \ ]) 45 | 46 | call quickui#menu#install('H&elp', [ 47 | \ ["&Cheatsheet", 'help index', ''], 48 | \ ['T&ips', 'help tips', ''], 49 | \ ['--',''], 50 | \ ["&Tutorial", 'help tutor', ''], 51 | \ ['&Quick Reference', 'help quickref', ''], 52 | \ ['&Summary', 'help summary', ''], 53 | \ ['--',''], 54 | \ ['&Vim Script', 'help eval', ''], 55 | \ ['&Function List', 'help function-list', ''], 56 | \ ], 10000) 57 | 58 | " display tips in the cmdline 59 | let g:quickui_show_tip = 1 60 | 61 | " press twice to open menu 62 | nnoremap :call quickui#menu#open() 63 | 64 | -------------------------------------------------------------------------------- /test/example_menu.vim: -------------------------------------------------------------------------------- 1 | 2 | "---------------------------------------------------------------------- 3 | " testing suit 4 | "---------------------------------------------------------------------- 5 | if 1 6 | call quickui#menu#switch('test') 7 | call quickui#menu#reset() 8 | call quickui#menu#install('H&elp', [ 9 | \ [ '&Content', 'echo 4' ], 10 | \ [ '&About', 'echo 5' ], 11 | \ ]) 12 | call quickui#menu#install('&File', [ 13 | \ [ "&New File\tCtrl+n", 'echo 0' ], 14 | \ [ "&Open File\t(F3)", 'echo 1' ], 15 | \ [ "&Close", 'echo 2' ], 16 | \ [ "--", '' ], 17 | \ [ "&Save\tCtrl+s", 'echo 3'], 18 | \ [ "Save &As", 'echo 4' ], 19 | \ [ "Save All", 'echo 5' ], 20 | \ [ "--", '' ], 21 | \ [ "E&xit\tAlt+x", 'echo 6' ], 22 | \ ]) 23 | call quickui#menu#install('&Edit', [ 24 | \ [ '&Copy', 'echo 1'], 25 | \ [ '&Paste', 'echo 2'], 26 | \ [ '&Find', 'echo 3'], 27 | \ ]) 28 | call quickui#menu#install('&Tools', [ 29 | \ [ '&Copy', 'echo 1'], 30 | \ [ '&Paste', 'echo 2'], 31 | \ [ '&Find', 'echo 3'], 32 | \ ]) 33 | 34 | call quickui#menu#install('&Window', []) 35 | call quickui#menu#change_weight('H&elp', 1000) 36 | call quickui#menu#switch('system') 37 | call quickui#menu#open('test') 38 | endif 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /test/menu_example.vim: -------------------------------------------------------------------------------- 1 | "====================================================================== 2 | " 3 | " menu_init.vim - 4 | " 5 | " Created by skywind on 2019/12/26 6 | " Last Modified: 2019/12/26 16:23:48 7 | " 8 | "====================================================================== 9 | 10 | if has('patch-8.1.2292') == 0 && exists('*nvim_open_win') == 0 11 | finish 12 | endif 13 | 14 | call quickui#menu#reset() 15 | 16 | call quickui#menu#install("&File", [ 17 | \ [ "&Open\t(:w)", 'call feedkeys(":tabe ")'], 18 | \ [ "&Save\t(:w)", 'write'], 19 | \ [ "--", ], 20 | \ [ "LeaderF &File", 'Leaderf file', 'Open file with leaderf'], 21 | \ [ "LeaderF &Mru", 'Leaderf mru --regexMode', 'Open recently accessed files'], 22 | \ [ "LeaderF &Buffer", 'Leaderf buffer', 'List current buffers in leaderf'], 23 | \ [ "--", ], 24 | \ [ "J&unk File", 'JunkFile', ''], 25 | \ ]) 26 | 27 | if has('win32') || has('win64') || has('win16') 28 | call quickui#menu#install('&File', [ 29 | \ [ "--", ], 30 | \ [ "Start &Cmd", 'silent !start /b cmd /C c:\drivers\clink\clink.cmd' ], 31 | \ [ "Start &PowerShell", 'silent !start powershell.exe' ], 32 | \ [ "Open &Explore", 'call Show_Explore()' ], 33 | \ ]) 34 | endif 35 | 36 | call quickui#menu#install("&File", [ 37 | \ [ "--", ], 38 | \ [ "E&xit", 'qa' ], 39 | \ ]) 40 | 41 | call quickui#menu#install("&Edit", [ 42 | \ ['Copyright &Header', 'call feedkeys("\ ec")', 'Insert copyright information at the beginning'], 43 | \ ['&Trailing Space', 'call StripTrailingWhitespace()', ''], 44 | \ ['Update &ModTime', 'call UpdateLastModified()', ''], 45 | \ ['&Paste Mode Line', 'PasteVimModeLine', ''], 46 | \ ['Format J&son', '%!python -m json.tool', ''], 47 | \ ['--'], 48 | \ ['&Align Table', 'Tabularize /|', ''], 49 | \ ['Align &Cheatsheet', 'MyCheatSheetAlign', ''], 50 | \ ]) 51 | 52 | call quickui#menu#install('&Symbol', [ 53 | \ [ "&Grep Word\t(In Project)", 'call MenuHelp_GrepCode()', 'Grep keyword in current project' ], 54 | \ [ "--", ], 55 | \ [ "Find &Definition\t(GNU Global)", 'call MenuHelp_Gscope("g")', 'GNU Global search g'], 56 | \ [ "Find &Symbol\t(GNU Global)", 'call MenuHelp_Gscope("s")', 'GNU Gloal search s'], 57 | \ [ "Find &Called by\t(GNU Global)", 'call MenuHelp_Gscope("d")', 'GNU Global search d'], 58 | \ [ "Find C&alling\t(GNU Global)", 'call MenuHelp_Gscope("c")', 'GNU Global search c'], 59 | \ [ "Find &From Ctags\t(GNU Global)", 'call MenuHelp_Gscope("z")', 'GNU Global search c'], 60 | \ [ "--", ], 61 | \ [ "Goto D&efinition\t(YCM)", 'YcmCompleter GoToDefinitionElseDeclaration'], 62 | \ [ "Goto &References\t(YCM)", 'YcmCompleter GoToReferences'], 63 | \ [ "Get D&oc\t(YCM)", 'YcmCompleter GetDoc'], 64 | \ [ "Get &Type\t(YCM)", 'YcmCompleter GetTypeImprecise'], 65 | \ ]) 66 | 67 | call quickui#menu#install('&Move', [ 68 | \ ["Quickfix &First\t:cfirst", 'cfirst', 'quickfix cursor rewind'], 69 | \ ["Quickfix L&ast\t:clast", 'clast', 'quickfix cursor to the end'], 70 | \ ["Quickfix &Next\t:cnext", 'cnext', 'cursor next'], 71 | \ ["Quickfix &Previous\t:cprev", 'cprev', 'quickfix cursor previous'], 72 | \ ]) 73 | 74 | call quickui#menu#install("&Build", [ 75 | \ ["File &Execute\tF5", 'AsyncTask file-run'], 76 | \ ["File &Compile\tF9", 'AsyncTask file-build'], 77 | \ ["File E&make\tF7", 'AsyncTask emake'], 78 | \ ["File &Start\tF8", 'AsyncTask emake-exe'], 79 | \ ['--', ''], 80 | \ ["&Project Build\tShift+F9", 'AsyncTask project-build'], 81 | \ ["Project &Run\tShift+F5", 'AsyncTask project-run'], 82 | \ ["Project &Test\tShift+F6", 'AsyncTask project-test'], 83 | \ ["Project &Init\tShift+F7", 'AsyncTask project-init'], 84 | \ ['--', ''], 85 | \ ["T&ask List\tCtrl+F10", 'call MenuHelp_TaskList()'], 86 | \ ['E&dit Task', 'AsyncTask -e'], 87 | \ ['Edit &Global Task', 'AsyncTask -E'], 88 | \ ['&Stop Building', 'AsyncStop'], 89 | \ ]) 90 | 91 | call quickui#menu#install("&Git", [ 92 | \ ['&View Diff', 'call svnhelp#svn_diff("%")'], 93 | \ ['&Show Log', 'call svnhelp#svn_log("%")'], 94 | \ ['File &Add', 'call svnhelp#svn_add("%")'], 95 | \ ]) 96 | 97 | 98 | if has('win32') || has('win64') || has('win16') || has('win95') 99 | call quickui#menu#install("&Git", [ 100 | \ ['--',''], 101 | \ ["Project &Update\t(Tortoise)", 'call svnhelp#tp_update()', 'TortoiseGit / TortoiseSvn'], 102 | \ ["Project &Commit\t(Tortoise)", 'call svnhelp#tp_commit()', 'TortoiseGit / TortoiseSvn'], 103 | \ ["Project L&og\t(Tortoise)", 'call svnhelp#tp_log()', 'TortoiseGit / TortoiseSvn'], 104 | \ ["Project &Diff\t(Tortoise)", 'call svnhelp#tp_diff()', 'TortoiseGit / TortoiseSvn'], 105 | \ ['--',''], 106 | \ ["File &Add\t(Tortoise)", 'call svnhelp#tf_add()', 'TortoiseGit / TortoiseSvn'], 107 | \ ["File &Blame\t(Tortoise)", 'call svnhelp#tf_blame()', 'TortoiseGit / TortoiseSvn'], 108 | \ ["File Co&mmit\t(Tortoise)", 'call svnhelp#tf_commit()', 'TortoiseGit / TortoiseSvn'], 109 | \ ["File D&iff\t(Tortoise)", 'call svnhelp#tf_diff()', 'TortoiseGit / TortoiseSvn'], 110 | \ ["File &Revert\t(Tortoise)", 'call svnhelp#tf_revert()', 'TortoiseGit / TortoiseSvn'], 111 | \ ["File Lo&g\t(Tortoise)", 'call svnhelp#tf_log()', 'TortoiseGit / TortoiseSvn'], 112 | \ ]) 113 | endif 114 | 115 | call quickui#menu#install('&Tools', [ 116 | \ ['Compare &History', 'call svnhelp#compare_ask_file()', ''], 117 | \ ['&Compare Buffer', 'call svnhelp#compare_ask_buffer()', ''], 118 | \ ['--',''], 119 | \ ['List &Buffer', 'call quickui#tools#list_buffer("FileSwitch tabe")', ], 120 | \ ['List &Function', 'call quickui#tools#list_function()', ], 121 | \ ['Display &Messages', 'call quickui#tools#display_messages()', ], 122 | \ ['--',''], 123 | \ ["&DelimitMate %{get(b:, 'delimitMate_enabled', 0)? 'Disable':'Enable'}", 'DelimitMateSwitch'], 124 | \ ['Read &URL', 'call menu#ReadUrl()', 'load content from url into current buffer'], 125 | \ ['&Spell %{&spell? "Disable":"Enable"}', 'set spell!', 'Toggle spell check %{&spell? "off" : "on"}'], 126 | \ ['&Profile Start', 'call MonitorInit()', ''], 127 | \ ['Profile S&top', 'call MonitorExit()', ''], 128 | \ ["Relati&ve number %{&relativenumber? 'OFF':'ON'}", 'set relativenumber!'], 129 | \ ["Proxy &Enable", 'call MenuHelp_Proxy(1)', 'setup http_proxy/https_proxy/all_proxy'], 130 | \ ["Proxy D&isable", 'call MenuHelp_Proxy(0)', 'clear http_proxy/https_proxy/all_proxy'], 131 | \ ]) 132 | 133 | call quickui#menu#install('&Plugin', [ 134 | \ ["&NERDTree\ttn", 'NERDTreeToggle', 'toggle nerdtree'], 135 | \ ['&Tagbar', '', 'toggle tagbar'], 136 | \ ["&Choose Window/Tab\tAlt+e", "ChooseWin", "fast switch win/tab with vim-choosewin"], 137 | \ ["-"], 138 | \ ["&Browse in github\trhubarb", "Gbrowse", "using tpope's rhubarb to open browse and view the file"], 139 | \ ["&Startify", "Startify", "using tpope's rhubarb to open browse and view the file"], 140 | \ ["&Gist", "Gist", "open gist with mattn/gist-vim"], 141 | \ ["&Edit Note", "Note", "edit note with vim-notes"], 142 | \ ["&Display Calendar", "Calendar", "display a calender"], 143 | \ ['Toggle &Vista', 'Vista!!', ''], 144 | \ ["-"], 145 | \ ["Plugin &List", "PlugList", "Update list"], 146 | \ ["Plugin &Update", "PlugUpdate", "Update plugin"], 147 | \ ]) 148 | 149 | call quickui#menu#install('Help (&?)', [ 150 | \ ["&Index", 'tab help index', ''], 151 | \ ['Ti&ps', 'tab help tips', ''], 152 | \ ['--',''], 153 | \ ["&Tutorial", 'tab help tutor', ''], 154 | \ ['&Quick Reference', 'tab help quickref', ''], 155 | \ ['&Summary', 'tab help summary', ''], 156 | \ ['--',''], 157 | \ ['&Vim Script', 'tab help eval', ''], 158 | \ ['&Function List', 'tab help function-list', ''], 159 | \ ['&Dash Help', 'call asclib#utils#dash_ft(&ft, expand(""))'], 160 | \ ], 10000) 161 | 162 | " let g:quickui_show_tip = 1 163 | 164 | 165 | "---------------------------------------------------------------------- 166 | " context menu 167 | "---------------------------------------------------------------------- 168 | let g:context_menu_k = [ 169 | \ ["&Peek Definition\tAlt+;", 'call quickui#tools#preview_tag("")'], 170 | \ ["S&earch in Project\t\\cx", 'exec "silent! GrepCode! " . expand("")'], 171 | \ [ "--", ], 172 | \ [ "Find &Definition\t\\cg", 'call MenuHelp_Fscope("g")', 'GNU Global search g'], 173 | \ [ "Find &Symbol\t\\cs", 'call MenuHelp_Fscope("s")', 'GNU Gloal search s'], 174 | \ [ "Find &Called by\t\\cd", 'call MenuHelp_Fscope("d")', 'GNU Global search d'], 175 | \ [ "Find C&alling\t\\cc", 'call MenuHelp_Fscope("c")', 'GNU Global search c'], 176 | \ [ "Find &From Ctags\t\\cz", 'call MenuHelp_Fscope("z")', 'GNU Global search c'], 177 | \ [ "--", ], 178 | \ [ "Goto D&efinition\t(YCM)", 'YcmCompleter GoToDefinitionElseDeclaration'], 179 | \ [ "Goto &References\t(YCM)", 'YcmCompleter GoToReferences'], 180 | \ [ "Get D&oc\t(YCM)", 'YcmCompleter GetDoc'], 181 | \ [ "Get &Type\t(YCM)", 'YcmCompleter GetTypeImprecise'], 182 | \ [ "--", ], 183 | \ ['Dash &Help', 'call asclib#utils#dash_ft(&ft, expand(""))'], 184 | \ ['Cpp&man', 'exec "Cppman " . expand("")', '', 'c,cpp'], 185 | \ ['P&ython Doc', 'call quickui#tools#python_help("")', 'python'], 186 | \ ] 187 | 188 | 189 | "---------------------------------------------------------------------- 190 | " hotkey 191 | "---------------------------------------------------------------------- 192 | nnoremap :call quickui#menu#open() 193 | 194 | nnoremap K :call quickui#tools#clever_context('k', g:context_menu_k, {}) 195 | 196 | if has('gui_running') || has('nvim') 197 | noremap :call MenuHelp_TaskList() 198 | endif 199 | 200 | 201 | -------------------------------------------------------------------------------- /test/test_confirm.vim: -------------------------------------------------------------------------------- 1 | " let g:quickui_confirm_border = 1 2 | 3 | let question = "What do you want ?" 4 | let choices = "&Apples\n&Oranges\n&Bananas" 5 | 6 | let choice = quickui#confirm#open(question, choices, 2, 'Confirm') 7 | 8 | if choice == 0 9 | echo "make up your mind!" 10 | elseif choice == 3 11 | echo "tasteful" 12 | else 13 | echo "I prefer bananas myself." 14 | endif 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/test_listbox.vim: -------------------------------------------------------------------------------- 1 | "---------------------------------------------------------------------- 2 | " testing suit 3 | "---------------------------------------------------------------------- 4 | if 1 5 | let lines = [ 6 | \ "[1]\tOpen &File\t(F3)", 7 | \ "[2]\tChange &Directory\t(F2)", 8 | \ "[3]\tHelp", 9 | \ "", 10 | \ "[4]\tE&xit", 11 | \ "[4]\t哈哈哈E&xit", 12 | \ ] 13 | for ix in range(1000) 14 | let lines += ['line: ' . ix] 15 | endfor 16 | function! MyCallback(code) 17 | let hwnd = g:quickui#listbox#current 18 | let context = hwnd.context 19 | echo "exit: ". a:code . ' context: '. context . ' in: ' . hwnd.tag 20 | endfunc 21 | let opts = {'title':'Select', 'border':1, 'index':400, 'close':'button'} 22 | let opts.context = 'asdfasdf' 23 | let opts.callback = 'MyCallback' 24 | let opts.border = 0 25 | " let opts.title = '' 26 | " let opts.close = 'none' 27 | let opts.bordercolor = 'WildMenu' 28 | let opts.keymap = {'=':'TAG:2', '-':'TAG:3'} 29 | if 0 30 | let inst = quickui#listbox#open(lines, opts) 31 | call popup_show(inst.winid) 32 | else 33 | let code = quickui#listbox#inputlist(lines, opts) 34 | echo "code: " . code 35 | endif 36 | endif 37 | 38 | if 0 39 | let content = [ 40 | \ [ 'echo 1', 'echo 100' ], 41 | \ [ 'echo 2', 'echo 200' ], 42 | \ [ 'echo 3', 'echo 300' ], 43 | \ [ 'echo 4' ], 44 | \ [], 45 | \ [ 'echo 5', 'echo 500' ], 46 | \] 47 | let opts = {'title': 'select'} 48 | call quickui#listbox#any(content, opts) 49 | endif 50 | 51 | 52 | if 0 53 | let content = [ 54 | \ [ 'echo 1', 'echo 100' ], 55 | \ [ 'echo 2', 'echo 200' ], 56 | \ [ 'echo 3', 'echo 300' ], 57 | \ [ 'echo 4' ], 58 | \ [ 'echo 5', 'echo 500' ], 59 | \] 60 | let opts = {'title': 'select'} 61 | call quickui#listbox#open(content, opts) 62 | endif 63 | 64 | if 0 65 | let linelist = [ 66 | \ "line 1", 67 | \ "line 2", 68 | \ "line 3" ] 69 | echo quickui#listbox#inputlist(linelist, {'title':'select'}) 70 | endif 71 | 72 | -------------------------------------------------------------------------------- /test/test_nvim_context.vim: -------------------------------------------------------------------------------- 1 | 2 | if 1 3 | call quickui#utils#highlight('default') 4 | let lines = [ 5 | \ "&New File\tCtrl+n", 6 | \ "&Open File\tCtrl+o", 7 | \ ["&Close", 'echo "test"'], 8 | \ "--", 9 | \ "&Save\tCtrl+s", 10 | \ "Save &As", 11 | \ "Save All", 12 | \ "-", 13 | \ "&User Menu\tF9", 14 | \ "&Dos Shell", 15 | \ "~&Time %{&undolevels? '+':'-'}", 16 | \ "--", 17 | \ "E&xit\tAlt+x", 18 | \ "&Help", 19 | \ ] 20 | " echo quickui#core#pattern_ascii 21 | " let menu = quickui#context#menu_compile(lines, 1) 22 | let opts = {'cursor': -1, 'line2':'cursor+1', 'col2': 'cursor', 'horizon':1} 23 | " let opts.index = 2 24 | let opts.callback = 'MyCallback' 25 | function! MyCallback(code) 26 | echo "callback: " . a:code 27 | endfunc 28 | let menu = quickui#context#open(lines, opts) 29 | endif 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /test/test_nvim_list.vim: -------------------------------------------------------------------------------- 1 | 2 | 3 | "---------------------------------------------------------------------- 4 | " 5 | "---------------------------------------------------------------------- 6 | function! s:nvim_create_listbox(textlist, opts) 7 | let hwnd = {} 8 | let opts = {} 9 | let items = quickui#listbox#parse(a:textlist) 10 | let bid = quickui#core#neovim_buffer('listbox', items.image) 11 | let hwnd.items = items 12 | let hwnd.bid = bid 13 | let hwnd.keymap = quickui#utils#keymap() 14 | let hwnd.hotkey = items.keymap 15 | let hwnd.opts = deepcopy(a:opts) 16 | let hwnd.context = has_key(a:opts, 'context')? a:opts.context : {} 17 | let w = has_key(a:opts, 'w')? a:opts.w + 2 : items.displaywidth 18 | let h = has_key(a:opts, 'h')? a:opts.h : items.nrows 19 | if h + 6 > &lines 20 | let h = &lines - 6 21 | let h = (h < 1)? 1 : h 22 | endif 23 | if w + 4 > &columns 24 | let w = &columns - 4 25 | let w = (w < 1)? 1 : w 26 | endif 27 | let opts = {'width':w, 'height':h, 'focusable':1, 'style':'minimal'} 28 | let opts.relative = 'editor' 29 | if has_key(a:opts, 'line') 30 | let opts.row = a:opts.line - 1 31 | else 32 | let limit1 = (&lines - 2) * 80 / 100 33 | let limit2 = (&lines - 2) 34 | if h + 4 < limit1 35 | let opts.row = (limit1 - h) / 2 - 1 36 | else 37 | let opts.row = (limit2 - h) / 2 - 1 38 | endif 39 | let opts.row = (opts.row < 0)? 0 : opts.row 40 | endif 41 | if has_key(a:opts, 'col') 42 | let opts.col = a:opts.col - 1 43 | else 44 | let opts.col = (&columns - w) / 2 - 1 45 | endif 46 | let border = get(a:opts, 'border', g:quickui#style#border) 47 | let background = -1 48 | let hwnd.opts.color = get(a:opts, 'color', 'QuickBG') 49 | let color = hwnd.opts.color 50 | let winid = nvim_open_win(bid, 0, opts) 51 | let button = (get(a:opts, 'close', '') == 'button')? 1 : 0 52 | if border > 0 && get(g:, 'quickui_nvim_simulate_border', 1) != 0 53 | let title = has_key(a:opts, 'title')? ' ' . a:opts.title . ' ' : '' 54 | let back = quickui#utils#make_border(w, h, border, title, button) 55 | let nbid = quickui#core#neovim_buffer('listborder', back) 56 | let op = {'relative':'editor', 'focusable':1, 'style':'minimal'} 57 | let op.width = w + 2 58 | let op.height = h + 2 59 | let op.row = opts.row - 1 60 | let op.col = opts.col - 1 61 | let background = nvim_open_win(nbid, 0, op) 62 | call nvim_win_set_option(background, 'winhl', 'Normal:'. color) 63 | endif 64 | let hwnd.winid = winid 65 | call nvim_win_set_option(winid, 'winhl', 'Normal:'. color) 66 | if get(a:opts, 'index', 0) >= 0 67 | let moveto = get(a:opts, 'index', 0) + 1 68 | call quickui#core#win_execute(winid, 'normal! ggG') 69 | call quickui#core#win_execute(winid, ':' . moveto) 70 | endif 71 | let border = get(a:opts, 'border', 1) 72 | let keymap = hwnd.keymap 73 | if !has_key(a:opts, 'horizon') 74 | let keymap["\"] = 'HALFUP' 75 | let keymap["\"] = 'HALFDOWN' 76 | let keymap["h"] = 'HALFUP' 77 | let keymap["l"] = 'HALFDOWN' 78 | endif 79 | if has_key(a:opts, 'keymap') 80 | for key in keys(a:opts.keymap) 81 | let keymap[key] = a:opts.keymap[key] 82 | endfor 83 | endif 84 | let hwnd.state = 1 85 | let hwnd.code = 0 86 | let hwnd.tag = '' 87 | if has_key(a:opts, 'syntax') 88 | let syntax = fnameescape(a:opts.syntax) 89 | call quickui#core#win_execute(winid, 'set ft=' . syntax) 90 | endif 91 | call quickui#listbox#highlight_keys(winid, items) 92 | call quickui#core#win_execute(winid, "setlocal cursorline scrolloff=0") 93 | let retval = -1 94 | while 1 95 | redraw! 96 | try 97 | let code = getchar() 98 | catch /^Vim:Interrupt$/ 99 | let code = "\" 100 | endtry 101 | let ch = (type(code) == v:t_number)? nr2char(code) : code 102 | if ch == "\" || ch == "\" 103 | break 104 | elseif ch == "\" || ch == "\" 105 | let retval = quickui#utils#get_cursor(winid) - 1 106 | break 107 | elseif ch == "\" 108 | if v:mouse_winid == winid 109 | if v:mouse_lnum > 0 110 | let cmd = ':' . v:mouse_lnum 111 | call quickui#core#win_execute(winid, cmd) 112 | redraw! 113 | sleep 10m 114 | let retval = v:mouse_lnum - 1 115 | break 116 | endif 117 | elseif v:mouse_winid == background 118 | if button != 0 && v:mouse_lnum == 1 119 | if v:mouse_col == w + 2 120 | break 121 | endif 122 | endif 123 | endif 124 | elseif has_key(hwnd.hotkey, ch) 125 | let retval = hwnd.hotkey[ch] 126 | break 127 | elseif has_key(keymap, ch) 128 | let key = keymap[ch] 129 | if strpart(key, 0, 4) == 'TAG:' 130 | let hwnd.tag = strpart(key, 4) 131 | let retval = quickui#utils#get_cursor(winid) - 1 132 | break 133 | elseif key == "ESC" 134 | break 135 | else 136 | let cmd = 'quickui#listbox#cursor_movement("' . key . '")' 137 | call quickui#core#win_execute(winid, 'call ' . cmd) 138 | endif 139 | endif 140 | endwhile 141 | let hwnd.code = retval 142 | if retval > 0 143 | call quickui#core#win_execute(winid, ':' . (retval + 1)) 144 | endif 145 | call nvim_win_close(winid, 0) 146 | if background >= 0 147 | call nvim_win_close(background, 0) 148 | endif 149 | redraw! 150 | let hwnd.state = 0 151 | let g:quickui#listbox#current = hwnd 152 | if has_key(hwnd.opts, 'callback') 153 | let F = function(hwnd.opts.callback) 154 | call F(retval) 155 | endif 156 | if retval >= 0 && retval < hwnd.items.nrows 157 | let cmd = hwnd.items.cmds[retval] 158 | if cmd != '' 159 | exec cmd 160 | endif 161 | endif 162 | return retval 163 | endfunc 164 | 165 | 166 | if 1 167 | let content = [ 168 | \ ["[1]\tOpen &File\t(F3)", 'echo 1'], 169 | \ ["[2]\tChange &Directory\t(F2)", 'echo 2'], 170 | \ ["[3]\tHelp", 'echo 3'], 171 | \ "", 172 | \ "[4]\tE&xit", 173 | \ "[5]\t哈哈哈E&xit", 174 | \ ] 175 | " let content = [] 176 | for ix in range(1000) 177 | let content += ['line: ' . ix] 178 | endfor 179 | function! MyCallback(code) 180 | let hwnd = g:quickui#listbox#current 181 | let context = hwnd.context 182 | echo "exit: ". a:code . ' context: '. context . ' tag: ' . hwnd.tag 183 | endfunc 184 | let opts = {'title': 'select', 'context':'hahaha', 'close':'button'} 185 | let opts.index = 400 186 | let opts.border = 2 187 | let opts.keymap = {'=':'TAG:1', '+':'TAG:1024'} 188 | let opts.callback = 'MyCallback' 189 | call quickui#listbox#open(content, opts) 190 | " call s:nvim_create_listbox(content, opts) 191 | endif 192 | 193 | 194 | -------------------------------------------------------------------------------- /test/test_nvim_menu.vim: -------------------------------------------------------------------------------- 1 | 2 | 3 | if 1 4 | call quickui#menu#switch('test') 5 | call quickui#menu#reset() 6 | call quickui#menu#install('H&elp', [ 7 | \ [ '&Content', 'echo 4' ], 8 | \ [ '&About', 'echo 5' ], 9 | \ ]) 10 | call quickui#menu#install('&File', [ 11 | \ [ "&New File\tCtrl+n", '' ], 12 | \ [ "&Open File\t(F3)", 'echo 1' ], 13 | \ [ "&Close", 'echo 3' ], 14 | \ [ "--", '' ], 15 | \ [ "&Save\tCtrl+s", ''], 16 | \ [ "Save &As", '' ], 17 | \ [ "Save All", '' ], 18 | \ [ "--", '' ], 19 | \ [ "E&xit\tAlt+x", '' ], 20 | \ ]) 21 | call quickui#menu#install('&Edit', [ 22 | \ [ '&Copy', 'echo 1', 'help1' ], 23 | \ [ '&Paste', 'echo 2', 'help2' ], 24 | \ [ '&Find', 'echo 3', 'help3' ], 25 | \ ]) 26 | call quickui#menu#install('&Tools', [ 27 | \ [ '&Copy', 'echo 1', 'help1' ], 28 | \ [ '&Paste', 'echo 2', 'help2' ], 29 | \ [ '&Find', 'echo 3', 'help3' ], 30 | \ ]) 31 | 32 | call quickui#menu#install('&Window', []) 33 | call quickui#menu#change_weight('H&elp', 1000) 34 | call quickui#menu#switch('system') 35 | let opts = {'name':'test'} 36 | call quickui#menu#nvim_open_menu(opts) 37 | " call quickui#menu#open('test') 38 | endif 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /test/test_nvim_popup.vim: -------------------------------------------------------------------------------- 1 | 2 | let buf = nvim_create_buf(v:false, v:true) 3 | call nvim_buf_set_lines(buf, 0, -1, v:true, ["test1", "text2", "line3"]) 4 | let opts = {'relative': 'editor', 'width': 10, 'height': 3, 'col': 0, 5 | \ 'row': -1, 'anchor': 'NW', 'style': 'minimal'} 6 | let win = nvim_open_win(buf, 0, opts) 7 | " optional: change highlight, otherwise Pmenu is used 8 | " call nvim_win_set_option(win, 'winhl', 'Normal:MyHighlight') 9 | 10 | redraw 11 | echo buf 12 | call getchar() 13 | call nvim_win_close(win, 0) 14 | call nvim_buf_set_lines(buf, 0, -1, v:true, ["suck" ]) 15 | " exec "bd! ". buf 16 | -------------------------------------------------------------------------------- /test/test_nvim_textbox.vim: -------------------------------------------------------------------------------- 1 | 2 | if 1 3 | let lines = [] 4 | for i in range(2000) 5 | let lines += ['printf("%d\n", ' . (i + 1) . ');'] 6 | endfor 7 | let opts = {'close':'button'} 8 | let opts.index = 1 9 | let opts.resize = 1 10 | let opts.title = "title" 11 | let opts.syntax = "cpp" 12 | " let opts.color = "QuickBox" 13 | " let opts.bordercolor = "QuickBG" 14 | " let opts.cursor = 38 15 | " let opts.number = 1 16 | " let opts.exit_on_click = 0 17 | " let winid = quickui#textbox#open(lines, opts) 18 | " call getchar() 19 | " call quickui#textbox#close(winid) 20 | call quickui#textbox#create(lines, opts) 21 | endif 22 | 23 | 24 | -------------------------------------------------------------------------------- /test/test_readline.vim: -------------------------------------------------------------------------------- 1 | "---------------------------------------------------------------------- 2 | " test suit 3 | "---------------------------------------------------------------------- 4 | function! s:test() 5 | let v:errors = [] 6 | let obj = quickui#readline#new() 7 | call obj.set('0123456789') 8 | call assert_equal('0123456789', obj.update(), 'test set') 9 | call obj.insert('ABC') 10 | call assert_equal('ABC0123456789', obj.update(), 'test insert') 11 | call obj.delete(3) 12 | call assert_equal('ABC3456789', obj.update(), 'test delete') 13 | call obj.backspace(2) 14 | call assert_equal('A3456789', obj.update(), 'test backspace') 15 | call obj.delete(1000) 16 | call assert_equal('A', obj.update(), 'test kill right') 17 | call obj.insert('BCD') 18 | call assert_equal('ABCD', obj.update(), 'test append') 19 | call obj.delete(1000) 20 | call assert_equal('ABCD', obj.update(), 'test append') 21 | call obj.backspace(1000) 22 | call assert_equal('', obj.update(), 'test append') 23 | call obj.insert('0123456789') 24 | call assert_equal('0123456789', obj.update(), 'test reinit') 25 | call obj.move(3) 26 | call obj.replace('abcd') 27 | call assert_equal('012abcd789', obj.update(), 'test replace') 28 | let obj.select = obj.cursor 29 | call obj.seek(-2, 1) 30 | call obj.visual_delete() 31 | call assert_equal('012ab789', obj.update(), 'test visual delete') 32 | let obj.select = obj.cursor 33 | call obj.seek(2, 1) 34 | " echo obj.display() 35 | call assert_equal('78', obj.visual_text(), 'test visual selection') 36 | call obj.visual_delete() 37 | call assert_equal('012ab9', obj.update(), 'test visual delete2') 38 | call obj.seek(-2, 1) 39 | if len(v:errors) 40 | for error in v:errors 41 | echoerr error 42 | endfor 43 | else 44 | echo "all passed" 45 | endif 46 | call obj.move(1) 47 | let obj.select = 4 48 | " echo obj.display() 49 | return obj.update() 50 | endfunc 51 | 52 | call s:test() 53 | 54 | -------------------------------------------------------------------------------- /test/test_readline2.vim: -------------------------------------------------------------------------------- 1 | 2 | 3 | "---------------------------------------------------------------------- 4 | " cli test 5 | "---------------------------------------------------------------------- 6 | function! s:test(prompt) 7 | let rl = quickui#readline#new() 8 | let index = 0 9 | let accept = '' 10 | let pos = 0 11 | while 1 12 | noautocmd redraw 13 | echohl Question 14 | echon a:prompt 15 | let ts = float2nr(reltimefloat(reltime()) * 1000) 16 | if 0 17 | call rl.echo(rl.blink(ts)) 18 | else 19 | let size = 15 20 | let pos = rl.slide(pos, size) 21 | echohl Title 22 | echon "<" 23 | call rl.echo(rl.blink(ts), pos, size) 24 | echohl Title 25 | echon ">" 26 | echon " cursor=" . rl.cursor 27 | echon " pos=". pos 28 | endif 29 | " echon rl.display() 30 | try 31 | let code = getchar(0) 32 | catch /^Vim:Interrupt$/ 33 | let code = "\" 34 | endtry 35 | if type(code) == v:t_number && code == 0 36 | try 37 | exec 'sleep 15m' 38 | continue 39 | catch /^Vim:Interrupt$/ 40 | let code = "\" 41 | endtry 42 | endif 43 | let ch = (type(code) == v:t_number)? nr2char(code) : code 44 | if ch == "" 45 | continue 46 | elseif ch == "\" 47 | break 48 | elseif ch == "\" 49 | let accept = rl.update() 50 | break 51 | else 52 | call rl.feed(ch) 53 | endif 54 | endwhile 55 | echohl None 56 | noautocmd redraw 57 | echo "" 58 | return accept 59 | endfunc 60 | 61 | call s:test('>>> ') 62 | 63 | 64 | -------------------------------------------------------------------------------- /test/test_terminal.vim: -------------------------------------------------------------------------------- 1 | function! TermExit(code) 2 | echom "terminal exit code: ". a:code 3 | echom "current win: ". winnr() 4 | endfunc 5 | 6 | let opts = {'w':80, 'h':24, 'callback':'TermExit'} 7 | let opts.title = 'Terminal Popup' 8 | call quickui#terminal#open('python', opts) 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/test_textbox.vim: -------------------------------------------------------------------------------- 1 | 2 | if 1 3 | let lines = [] 4 | for i in range(2000) 5 | let lines += ['printf("%d\n", ' . (i + 1) . ');'] 6 | endfor 7 | let opts = {} 8 | let opts.index = 30 9 | let opts.resize = 1 10 | let opts.title = "title" 11 | let opts.syntax = "cpp" 12 | let opts.color = "QuickPreview" 13 | let opts.bordercolor = 'WildMenu' 14 | " let opts.bordercolor = "QuickBG" 15 | " let opts.title = '' 16 | " let opts.border = 0 17 | let opts.cursor = 38 18 | let opts.number = 1 19 | " let opts.exit_on_click = 0 20 | let winid = quickui#textbox#open(lines, opts) 21 | " call getchar() 22 | " call quickui#textbox#close(winid) 23 | endif 24 | 25 | -------------------------------------------------------------------------------- /test/test_window.vim: -------------------------------------------------------------------------------- 1 | let opts = {} 2 | let opts.w = 40 3 | let opts.h = 5 4 | let opts.x = 40 5 | let opts.y = 2 6 | let opts.title = ' Hello, World ' 7 | let opts.border = 'default' 8 | let opts.padding = [0, 1, 0, 1] 9 | let opts.button = 1 10 | " let opts.center = 1 11 | " let opts.hide = 1 12 | let text = ['012345678901234567890123456789', 'abcdef'] 13 | 14 | let win = quickui#window#new() 15 | call win.open(text, opts) 16 | " call win.set_text(text) 17 | " call win.execute('setl number') 18 | 19 | 20 | redraw 21 | 22 | " echo win.opts 23 | 24 | call getchar() 25 | 26 | call win.show(0) 27 | redraw 28 | call getchar() 29 | 30 | call win.set_line(4, 'Hello, Vim World !!') 31 | call win.move(50, 10) 32 | call win.show(1) 33 | call win.resize(30, 7) 34 | call win.center() 35 | redraw 36 | echo win.quit 37 | call getchar() 38 | 39 | call win.close() 40 | 41 | " echo [win.w, win.h, win.info.tw, win.info.th] 42 | 43 | --------------------------------------------------------------------------------