├── .gitignore ├── LICENSE ├── README.md ├── autoload └── sharpenup │ ├── codeactions.vim │ ├── legacycsproj.vim │ └── statusline.vim ├── ftplugin └── cs │ └── sharpenup.vim └── plugin └── sharpenup.vim /.gitignore: -------------------------------------------------------------------------------- 1 | /tags 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Nick Jensen 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 | # Sharpen Up! 2 | 3 | This plugin is tightly integrated with [OmniSharp-vim](https://github.com/OmniSharp/omnisharp-vim) for C# development, providing default mappings and integrations that are better defined outside of OmniSharp-vim itself. 4 | 5 | ## Features 6 | 7 | * [Code actions available](#code-actions-available) flag in the sign column 8 | * Customisable [statusline](#statusline) function for displaying server status 9 | * Default [mappings](#mappings) 10 | * Manage file includes in [legacy .csproj](#legacy-csproj-actions) files 11 | 12 | ## 💡 Code actions available 13 | 14 | A flag is displayed in the sign column to indicate that one or more code actions are available. 15 | 16 | #### Options 17 | 18 | | Variable name | Default | | 19 | |------------------------------------------|----------------|--------------------------------------------------------------| 20 | | `g:sharpenup_codeactions` | `1` | Set to `0` to disable this feature | 21 | | `g:sharpenup_codeactions_autocmd` | `'CursorHold'` | Which autocmd to trigger on - can be a comma separated list. Suggestions: `CursorHold`, `CursorMoved`, `BufEnter,CursorMoved` | 22 | | `g:sharpenup_codeactions_glyph` | `'💡'` | Select the character to be used as the sign-column indicator | 23 | | `g:sharpenup_codeactions_set_signcolumn` | `1` | `'signcolumn'` will be set to `yes` for .cs buffers | 24 | 25 | ## Statusline 26 | 27 | The status of the current OmniSharp server can be added to your statusline using SharpenUp helper functions. 28 | The statusline flag can be particularly useful when working with multiple solutions in a single Vim session, as each buffer shows the status of the solution the buffer belongs to. 29 | It is also useful as an indicator of how many projects of a large solution have been loaded so far. 30 | 31 | Default: 32 | 33 | ![sharpenup_stl_loading_default_light](https://user-images.githubusercontent.com/5274565/87356346-06fa2d00-c5b6-11ea-91e6-ed89901d7afa.png) 34 | ![sharpenup_stl_loaded_default_light](https://user-images.githubusercontent.com/5274565/87356354-0a8db400-c5b6-11ea-84a3-54a05b6ba119.png) 35 | 36 | Customised: 37 | 38 | ![sharpenup_stl_loading_custom_light](https://user-images.githubusercontent.com/5274565/87356360-0d88a480-c5b6-11ea-94be-1b6d805c1c82.png) 39 | ![sharpenup_stl_loaded_custom_light](https://user-images.githubusercontent.com/5274565/87356367-0feafe80-c5b6-11ea-9d9a-28ea72e45b61.png) 40 | 41 | Integrated in lightline.vim: 42 | 43 | ![sharpenup_stl_loading_lightline_light](https://user-images.githubusercontent.com/5274565/87356379-137e8580-c5b6-11ea-9b47-b741a673fae4.png) 44 | 45 | 46 | **Note:** The statusline function does not support the HTTP server, Stdio only. 47 | 48 | #### Customisation 49 | 50 | The `g:sharpenup_statusline_opts` variable can be used to customise the text and highlighting of the statusline. 51 | 52 | The defaults are as follows: 53 | 54 | ```vim 55 | let g:sharpenup_statusline_opts = { 56 | \ 'TextLoading': ' O#: %s loading... (%p of %P) ', 57 | \ 'TextReady': ' O#: %s ', 58 | \ 'TextDead': ' O#: Not running ', 59 | \ 'Highlight': 1, 60 | \ 'HiLoading': 'SharpenUpLoading', 61 | \ 'HiReady': 'SharpenUpReady', 62 | \ 'HiDead': 'SharpenUpDead' 63 | \} 64 | ``` 65 | 66 | The following special items can be included: 67 | 68 | | | | 69 | |------|-------------------------------------------------------------------------| 70 | | `%s` | Solution/directory name of OmniSharp server associated with this buffer | 71 | | `%P` | Total number of projects in this solution | 72 | | `%p` | Number of projects loaded so far | 73 | 74 | The texts can be set individually, or using property `Text`. 75 | A shortcut is to simply assign a text value to `g:sharpenup_statusline_opts`, which is equivalent to only setting the `Text` property: 76 | 77 | ```vim 78 | " Use a single glyph in the statusline, and allow the highlight groups to indicate server status 79 | let g:sharpenup_statusline_opts = '•' 80 | ``` 81 | 82 | To change the highlight colours, either: 83 | 84 | * assign different highlight groups to be used: 85 | ```vim 86 | let g:sharpenup_statusline_opts = { 'HiLoading': 'NonText' } 87 | ``` 88 | * link the SharpenUp highlight groups to something else: 89 | ```vim 90 | highlight link SharpenUpReady ModeMsg 91 | ``` 92 | * set the SharpenUp highlight groups directly: 93 | ```vim 94 | highlight SharpenUpReady ctermfg=66 guifg=#458588 95 | ``` 96 | * or just disable highlighting: 97 | ```vim 98 | let g:sharpenup_statusline_opts = { 'Highlight': 0 } 99 | ``` 100 | 101 | #### Vanilla 102 | 103 | The simplest way to use the statusline function is to include it in `'statusline'`, e.g.: 104 | 105 | ```vim 106 | set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V 107 | let &statusline .= sharpenup#statusline#Build() 108 | set statusline+=\ %P 109 | ``` 110 | 111 | #### Lightline 112 | 113 | When using [lightline.vim](https://github.com/itchyny/lightline.vim) you can also include the OmniSharp server status with the `sharpenup#statusline#Build()` function. 114 | Here's an example: 115 | 116 | ```vim 117 | " Ensure that `g:sharpenup_statusline_opts` is set _before_ 118 | " `sharpenup#statusline#Build()` is called 119 | let g:sharpenup_statusline_opts = { 'Highlight': 0 } 120 | let g:lightline = { 121 | \ 'active': { 122 | \ 'right': [['lineinfo'], ['percent'], ['fileformat', 'fileencoding', 'filetype', 'sharpenup']] 123 | \ }, 124 | \ 'inactive': { 125 | \ 'right': [['lineinfo'], ['percent'], ['sharpenup']] 126 | \ }, 127 | \ 'component': { 128 | \ 'sharpenup': sharpenup#statusline#Build() 129 | \ } 130 | \} 131 | ``` 132 | 133 | Highlighting has been disabled in `g:sharpenup_statusline_opts` in this example, meaning that the default statusline texts will be displayed ("O#: Loading...", "O#", "O#: Not running") in the statusline colours. 134 | 135 | This will work fine but the statusline will only be updated when Vim asks for it, which typically happens on cursor movements and changes etc. To have the server status updated immediately when the server status changes, add this `autocmd`: 136 | 137 | ```vim 138 | augroup lightline_integration 139 | autocmd! 140 | autocmd User OmniSharpStarted,OmniSharpReady,OmniSharpStopped call lightline#update() 141 | augroup END 142 | ``` 143 | 144 | #### Airline 145 | 146 | [vim-airline](https://github.com/vim-airline/vim-airline) has OmniSharp-vim integration built-in - no vim-sharpenup integration is necessary. 147 | 148 | ## Mappings 149 | 150 | By default, vim-sharpenup creates standard OmniSharp-vim mappings in .cs buffers. 151 | This can be globally disabled like this: 152 | 153 | ```vim 154 | let g:sharpenup_create_mappings = 0 155 | ``` 156 | 157 | The mappings all use a common prefix, except for these exceptions: `gd`, ``, `[[`, `]]` 158 | 159 | The full list of mappings is as follows: 160 | 161 | |Action |LHS |Full default mapping | 162 | |----------------------------------|-------------|-----------------------------------------------------------------------------------------| 163 | |Go to definition |`gd` |`nmap gd (omnisharp_go_to_definition)` | 164 | |Go to type definition |prefix+`gt` |`nmap osgt (omnisharp_go_to_type_definition)` | 165 | |Find usages |prefix+`fu` |`nmap osfu (omnisharp_find_usages)` | 166 | |Find implementations |prefix+`fi` |`nmap osfi (omnisharp_find_implementations)` | 167 | |Preview definition |prefix+`pd` |`nmap ospd (omnisharp_preview_definition)` | 168 | |Preview implementations |prefix+`pi` |`nmap ospi (omnisharp_preview_implementations)` | 169 | |Type lookup |prefix+`t` |`nmap ost (omnisharp_type_lookup)` | 170 | |Show documentation |prefix+`d` |`nmap osd (omnisharp_documentation)` | 171 | |Find symbol |prefix+`fs` |`nmap osfs (omnisharp_find_symbol)` | 172 | |Find type |prefix+`ft` |`nmap osft (omnisharp_find_type)` | 173 | |Fix usings |prefix+`fx` |`nmap osfx (omnisharp_fix_usings)` | 174 | |Signature help (normal) |`` |`nmap (omnisharp_signature_help)` | 175 | |Signature help (insert) |`` |`imap (omnisharp_signature_help)` | 176 | |Navigate up |`[[` |`nmap [[ (omnisharp_navigate_up)` | 177 | |Navigate down |`]]` |`nmap ]] (omnisharp_navigate_down)` | 178 | |Global code check |prefix+`gcc` |`nmap osgcc (omnisharp_global_code_check)` | 179 | |Code actions (normal) |prefix+`ca` |`nmap osca (omnisharp_code_actions)` | 180 | |Code actions (visual) |prefix+`ca` |`xmap osca (omnisharp_code_actions)` | 181 | |Repeat last code action (normal) |prefix+`.` |`nmap os. (omnisharp_code_action_repeat)` | 182 | |Repeat last code action (visual) |prefix+`.` |`xmap os. (omnisharp_code_action_repeat)` | 183 | |Rename |prefix+`nm` |`nmap osnm (omnisharp_rename)` | 184 | |Code format |prefix+`=` |`nmap os= (omnisharp_code_format)` | 185 | |Restart server |prefix+`re` |`nmap osre (omnisharp_restart_server)` | 186 | |Start server |prefix+`st` |`nmap osst (omnisharp_start_server)` | 187 | |Stop server |prefix+`sp` |`nmap ossp (omnisharp_stop_server)` | 188 | |Run test under cursor |prefix+`rt` |`nmap osrt (omnisharp_run_test)` | 189 | |Run test under cursor (no build) |prefix+`rnt` |`nmap osrnt (omnisharp_run_test_no_build)` | 190 | |Run all tests in file |prefix+`rat` |`nmap osrat (omnisharp_run_tests_in_file)` | 191 | |Run all tests in file (no build) |prefix+`rant`|`nmap osrant (omnisharp_run_tests_in_file_no_build)`| 192 | |Debug test under cursor |prefix+`rdt` |`nmap osrdt (omnisharp_debug_test)` | 193 | |Debug test under cursor (no build)|prefix+`rdnt`|`nmap osrdnt (omnisharp_debug_test_no_build)` | 194 | 195 | The default prefix is `os`. 196 | Vim's default local-leader is `\` which means that the default prefixed mappings all begin with `\os`. 197 | This can be overridden either by changing `maplocalleader`, or setting a different prefix: 198 | 199 | ```vim 200 | " Creates “Find implementations” mapping: 'osfi' 201 | let maplocalleader = "\" 202 | 203 | " Creates “Find implementations” mapping: ',fi' 204 | let g:sharpenup_map_prefix = ',' 205 | ``` 206 | 207 | ## Legacy csproj actions 208 | 209 | In older .NET Framework projects, all .cs files are listed explicitly in the .csproj file. 210 | vim-sharpenup provides some functionality for maintaining this style of .csproj file, by adding and renaming referenced .cs files. 211 | 212 | The following commands are provided: 213 | 214 | - `:SharpenUpAddToProject` add the current .cs file to the .csproj file 215 | - `:SharpenUpRenameInProject` rename the current .cs file in the .csproj file, e.g. `:SharpenUpRenameInProject NewFilename.cs` 216 | 217 | When the `g:sharpenup_map_legacy_csproj_actions` flag is set (it is by default), the following mappings are also created (note that the `g:sharpenup_map_prefix` is used, see [mappings](#mappings)): 218 | 219 | |Action |LHS |Full default mapping | 220 | |-----------------------|------------|------------------------------------------------------------------------------------| 221 | |Add file to .csproj |prefix+`xa` |`nmap osxa (sharpenup_add_to_csproj)` | 222 | |Rename file in .csproj |prefix+`xr` |`nmap osxr (sharpenup_rename_in_csproj)` | 223 | 224 | The mapping to rename a file populates the vim command line with the `:SharpenUpRenameInProject` command and the current filename (relative to the .csproj file), and is used like this: 225 | 226 | ```sh 227 | :SharpenUpRenameInProject Path/To/NewFileName.cs 228 | ``` 229 | 230 | The `:SharpenUpRenameInProject` command can be configured to execute a callback function after successfully renaming a file in the .csproj file. 231 | Here you can script the physical rename of the file to match the name you have just set in the .csproj file. 232 | 233 | ```vim 234 | let g:sharpenup_legacy_csproj_rename_callback = 'MoveAfterProjectRename' 235 | ``` 236 | 237 | The `g:sharpenup_legacy_csproj_rename_callback` variable should be the name of a function which accepts 3 arguments: 238 | 239 | * `newname`: The new filename, with path relative to the .csproj file 240 | * `oldname`: The old filename, with path relative to the .csproj file 241 | * `project_dir`: The full path to the .csproj parent directory 242 | 243 | Example: Rename the file, in a *nix environment: 244 | 245 | ```vim 246 | function! MoveAfterProjectRename(newname, oldname, project_dir) 247 | call system('mkdir -p ' . a:project_dir . '/' . fnamemodify(a:newname, ':h')) 248 | call system('mv ' . a:project_dir . '/' . a:oldname . ' ' . a:project_dir . '/' . a:newname) 249 | execute 'edit' a:project_dir . '/' . a:newname 250 | bdelete # 251 | lcd . 252 | endfunction 253 | ``` 254 | 255 | Here's an example that makes use of [vim-eunuch](https://github.com/tpope/vim-eunuch)'s `:Move` command, which takes care of most of the details in the previous example and is OS-agnostic: 256 | 257 | ```vim 258 | function! MoveAfterProjectRename(newname, oldname, project_dir) 259 | execute 'lcd' a:project_dir 260 | execute 'Move' a:newname 261 | lcd . 262 | endfunction 263 | ``` 264 | -------------------------------------------------------------------------------- /autoload/sharpenup/codeactions.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpoptions 2 | set cpoptions&vim 3 | 4 | function! sharpenup#codeactions#Count() abort 5 | let opts = { 6 | \ 'CallbackCount': function('s:CBReturnCount', [bufnr(), line('.')]), 7 | \ 'CallbackCleanup': {-> execute('sign unplace * group=sharpenup_CodeActions')} 8 | \} 9 | call OmniSharp#actions#codeactions#Count(opts) 10 | endfunction 11 | 12 | function! s:CBReturnCount(bufnr, line, count) abort 13 | if a:count 14 | execute 'sign place 99' 15 | \ 'line=' . a:line 16 | \ 'name=sharpenup_CodeActions' 17 | \ 'group=sharpenup_CodeActions' 18 | \ 'file=' . bufname(a:bufnr) 19 | endif 20 | endfunction 21 | 22 | let &cpoptions = s:save_cpo 23 | unlet s:save_cpo 24 | 25 | " vim:et:sw=2:sts=2 26 | -------------------------------------------------------------------------------- /autoload/sharpenup/legacycsproj.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpoptions 2 | set cpoptions&vim 3 | 4 | function! s:HiEcho(message, ...) abort 5 | let group = a:0 ? a:1 : 'WarningMsg' 6 | execute 'echohl ' . group 7 | echomsg a:message 8 | echohl None 9 | endfunction 10 | 11 | " Search from the current directory up to the solution directory for a .csproj 12 | " file, and return the first one found. Note that this may return the wrong 13 | " .csproj file if two .csproj files are found in the same directory. 14 | function! s:FindProject() abort 15 | let l:base = fnamemodify(OmniSharp#FindSolutionOrDir(), ':h') 16 | let l:dir = expand('%:p:h') 17 | while 1 18 | let l:projects = split(globpath(l:dir, '*.csproj'), '\n') 19 | if len(l:projects) 20 | return l:projects[0] 21 | endif 22 | let l:parent = fnamemodify(l:dir, ':h') 23 | if l:dir ==# l:parent || l:dir ==# l:base 24 | call s:HiEcho('Project not found') 25 | return '' 26 | endif 27 | let l:dir = l:parent 28 | endwhile 29 | endfunction 30 | 31 | " Add the current file to the .csproj. The .csproj must be found in an ancestor 32 | " directory and must already contain at least one .cs file. 33 | function! sharpenup#legacycsproj#AddToProject() abort 34 | let l:filepath = expand('%:p') 35 | let l:project = s:FindProject() 36 | if !len(l:project) | return | endif 37 | let l:currenttab = tabpagenr() 38 | execute 'silent tabedit' l:project 39 | call cursor(1, 1) 40 | if !search('^\s*?/>?g 55 | endif 56 | silent write 57 | tabclose 58 | execute 'tabnext' l:currenttab 59 | endfunction 60 | 61 | " Find the current file in the .csproj file and rename it to a:newname. 62 | " Pass in a full path relative to the project. 63 | function! sharpenup#legacycsproj#RenameInProject(newname) abort 64 | let l:filepath = expand('%:p') 65 | let l:project = s:FindProject() 66 | if !len(l:project) | return | endif 67 | let l:currenttab = tabpagenr() 68 | execute 'silent tabedit' l:project 69 | call cursor(1, 1) 70 | let l:project_dir = fnamemodify(l:project, ':h') 71 | if l:project_dir !=# getcwd() 72 | execute 'lcd' fnamemodify(l:project, ':h') 73 | endif 74 | let l:filepath = fnamemodify(l:filepath, ':.') 75 | let l:oldname = l:filepath 76 | if g:OmniSharp_translate_cygwin_wsl 77 | let l:filepath = substitute(l:filepath, '/', '\\\\', 'g') 78 | elseif has('win32') 79 | let l:filepath = substitute(l:filepath, '\\', '\\\\', 'g') 80 | endif 81 | " Search for the full file path, relative to the .csproj 82 | if !search(l:filepath, '') 83 | tabclose 84 | execute 'tabnext' l:currenttab 85 | call s:HiEcho('Could not find ' . substitute(l:filepath, '\\\\', '\\', 'g')) 86 | return 87 | endif 88 | let l:newpath = a:newname 89 | if g:OmniSharp_translate_cygwin_wsl 90 | let l:newpath = substitute(a:newname, '/', '\\\\', 'g') 91 | elseif has('win32') 92 | let l:newpath = substitute(a:newname, '\\', '\\\\', 'g') 93 | endif 94 | execute 'substitute?' . l:filepath . '?' . l:newpath . '?' 95 | silent write 96 | tabclose 97 | execute 'tabnext' l:currenttab 98 | if get(g:, 'sharpenup_legacy_csproj_rename_callback', '') !=# '' 99 | try 100 | let CB = function(g:sharpenup_legacy_csproj_rename_callback) 101 | call CB(a:newname, l:oldname, l:project_dir) 102 | catch /^Vim\%((\a\+)\)\=:\%(E117\):/ 103 | call s:HiEcho( 104 | \ 'g:sharpenup_legacy_csproj_rename_callback function does not exist: ' 105 | \ . g:sharpenup_legacy_csproj_rename_callback) 106 | endtry 107 | endif 108 | endfunction 109 | 110 | " Populate the Vim command line with the :SharpenUpRenameInProject command and 111 | " the current filepath, ensuring that the filepath is relative to the project. 112 | function! sharpenup#legacycsproj#RenameInProjectPopulate() abort 113 | let l:filepath = expand('%:p') 114 | let l:project = s:FindProject() 115 | if !len(l:project) | return | endif 116 | let l:currenttab = tabpagenr() 117 | execute 'silent tabedit' l:project 118 | call cursor(1, 1) 119 | if fnamemodify(l:project, ':h') !=# getcwd() 120 | execute 'lcd' fnamemodify(l:project, ':h') 121 | endif 122 | let l:filepath = fnamemodify(l:filepath, ':.') 123 | tabclose 124 | execute 'tabnext' l:currenttab 125 | call feedkeys(':SharpenUpRenameInProject ' . l:filepath, 'n') 126 | endfunction 127 | 128 | let &cpoptions = s:save_cpo 129 | unlet s:save_cpo 130 | 131 | " vim:et:sw=2:sts=2 132 | -------------------------------------------------------------------------------- /autoload/sharpenup/statusline.vim: -------------------------------------------------------------------------------- 1 | let s:save_cpo = &cpoptions 2 | set cpoptions&vim 3 | 4 | let s:t_ignore = -1 5 | let s:t_loading = 0 6 | let s:t_ready = 1 7 | let s:t_dead = 2 8 | let s:t_invalid = 9 9 | function! sharpenup#statusline#GetStatus() abort 10 | call s:StatusInit() 11 | let status = { 12 | \ 'State': s:t_ignore, 13 | \ 'Text': '' 14 | \} 15 | if &filetype !=# 'cs' | return status | endif 16 | if !g:OmniSharp_server_stdio 17 | let status.State = s:t_invalid 18 | let status.Text = ' O#: Invalid server ' 19 | return status 20 | endif 21 | 22 | let host = OmniSharp#GetHost(bufnr('%')) 23 | if type(host.job) != v:t_dict || get(host.job, 'stopped') 24 | let status.State = s:t_dead 25 | let status.Text = substitute(s:statusOpts.TextDead, '%s', '-', 'g') 26 | return status 27 | endif 28 | 29 | let loaded = get(host.job, 'loaded', 0) 30 | let status.State = loaded ? s:t_ready : s:t_loading 31 | let status.Text = loaded ? s:statusOpts.TextReady : s:statusOpts.TextLoading 32 | if stridx(status.Text, '%s') >= 0 33 | let sod = fnamemodify(host.sln_or_dir, ':t') 34 | let status.Text = substitute(status.Text, '%s', sod, 'g') 35 | endif 36 | if match(status.Text, '%p\c') >= 0 37 | try 38 | let projectsloaded = OmniSharp#project#CountLoaded() 39 | let projectstotal = OmniSharp#project#CountTotal() 40 | catch 41 | " The CountLoaded and CountTotal functions are very new - catch the error 42 | " when they don't exist 43 | let projectsloaded = 0 44 | let projectstotal = 0 45 | endtry 46 | let status.Text = substitute(status.Text, '%p\C', projectsloaded, 'g') 47 | let status.Text = substitute(status.Text, '%P\C', projectstotal, 'g') 48 | endif 49 | return status 50 | endfunction 51 | 52 | function! sharpenup#statusline#StatusText(statustype) abort 53 | let status = sharpenup#statusline#GetStatus() 54 | return status.State == a:statustype ? status.Text : '' 55 | endfunction 56 | 57 | function! sharpenup#statusline#Build() abort 58 | call s:StatusInit() 59 | return 60 | \ sharpenup#statusline#BuildSegment(s:t_loading, s:statusOpts.HiLoading) . 61 | \ sharpenup#statusline#BuildSegment(s:t_ready, s:statusOpts.HiReady) . 62 | \ sharpenup#statusline#BuildSegment(s:t_dead, s:statusOpts.HiDead) 63 | endfunction 64 | 65 | function! sharpenup#statusline#BuildSegment(state, ...) abort 66 | let segment = '' 67 | if s:statusOpts.Highlight 68 | if a:0 69 | let group = a:1 70 | else 71 | let group = 72 | \ a:state == s:t_loading ? s:statusOpts.HiLoading : 73 | \ a:state == s:t_ready ? s:statusOpts.HiReady : 74 | \ a:state == s:t_dead ? s:statusOpts.HiDead : 'Normal' 75 | endif 76 | let segment .= '%#' . group . '#' 77 | endif 78 | let segment .= '%{sharpenup#statusline#StatusText(' . a:state . ')}' 79 | if s:statusOpts.Highlight 80 | let segment .= '%*' 81 | endif 82 | return segment 83 | endfunction 84 | 85 | function! s:StatusInit() abort 86 | if exists('s:statusOpts') | return | endif 87 | 88 | " Setup for first use 89 | let s:statusOpts = { 90 | \ 'TextLoading': ' O#: %s loading... (%p of %P) ', 91 | \ 'TextReady': ' O#: %s ', 92 | \ 'TextDead': ' O#: Not running ', 93 | \ 'Highlight': 1, 94 | \ 'HiLoading': 'SharpenUpLoading', 95 | \ 'HiReady': 'SharpenUpReady', 96 | \ 'HiDead': 'SharpenUpDead' 97 | \} 98 | if exists('g:sharpenup_statusline_opts') 99 | let gs = g:sharpenup_statusline_opts 100 | if type(gs) == type('') 101 | " A string value for g:sharpenup_statusline_opts replaces all status texts 102 | let s:statusOpts.TextLoading = gs 103 | let s:statusOpts.TextReady = gs 104 | let s:statusOpts.TextDead = gs 105 | elseif type(gs) == type({}) 106 | if has_key(gs, 'TextLoading') || has_key(gs, 'Text') 107 | let s:statusOpts.TextLoading = get(gs, 'TextLoading', get(gs, 'Text')) 108 | endif 109 | if has_key(gs, 'TextReady') || has_key(gs, 'Text') 110 | let s:statusOpts.TextReady = get(gs, 'TextReady', get(gs, 'Text')) 111 | endif 112 | if has_key(gs, 'TextDead') || has_key(gs, 'Text') 113 | let s:statusOpts.TextDead = get(gs, 'TextDead', get(gs, 'Text')) 114 | endif 115 | if !get(gs, 'Highlight', 1) 116 | let s:statusOpts.Highlight = 0 117 | endif 118 | if has_key(gs, 'HiLoading') 119 | let s:statusOpts.HiLoading = gs.HiLoading 120 | endif 121 | if has_key(gs, 'HiReady') 122 | let s:statusOpts.HiReady = gs.HiReady 123 | endif 124 | if has_key(gs, 'HiDead') 125 | let s:statusOpts.HiDead = gs.HiDead 126 | endif 127 | endif 128 | endif 129 | endfunction 130 | 131 | let &cpoptions = s:save_cpo 132 | unlet s:save_cpo 133 | 134 | " vim:et:sw=2:sts=2 135 | -------------------------------------------------------------------------------- /ftplugin/cs/sharpenup.vim: -------------------------------------------------------------------------------- 1 | if !get(g:, 'sharpenup_loaded', 0) | finish | endif 2 | if get(b:, 'sharpenup_ftplugin_loaded', 0) | finish | endif 3 | let b:undo_ftplugin = get(b:, 'undo_ftplugin', 'exe') 4 | let b:sharpenup_ftplugin_loaded = 1 5 | let b:undo_ftplugin .= '| unlet b:sharpenup_ftplugin_loaded' 6 | 7 | let s:save_cpo = &cpoptions 8 | set cpoptions&vim 9 | 10 | command! -buffer SharpenUpAddToProject call sharpenup#legacycsproj#AddToProject() 11 | command! -buffer -nargs=1 SharpenUpRenameInProject call sharpenup#legacycsproj#RenameInProject() 12 | 13 | nnoremap (sharpenup_add_to_csproj) :call sharpenup#legacycsproj#AddToProject() 14 | nnoremap (sharpenup_rename_in_csproj) :call sharpenup#legacycsproj#RenameInProjectPopulate() 15 | 16 | function! s:map(mode, lhs, plug) abort 17 | let l:rhs = '(' . a:plug . ')' 18 | if !hasmapto(l:rhs, substitute(a:mode, 'x', 'v', '')) 19 | \ && maparg(a:lhs, a:mode) ==# '' 20 | execute a:mode . 'map ' a:lhs l:rhs 21 | endif 22 | endfunction 23 | 24 | let s:pre = get(g:, 'sharpenup_map_prefix', "\os") 25 | 26 | if get(g:, 'sharpenup_create_mappings', 1) 27 | call s:map('n', 'gd', 'omnisharp_go_to_definition') 28 | call s:map('n', s:pre . 'gt', 'omnisharp_go_to_type_definition') 29 | call s:map('n', s:pre . 'fu', 'omnisharp_find_usages') 30 | call s:map('n', s:pre . 'fi', 'omnisharp_find_implementations') 31 | call s:map('n', s:pre . 'pd', 'omnisharp_preview_definition') 32 | call s:map('n', s:pre . 'pi', 'omnisharp_preview_implementation') 33 | 34 | call s:map('n', s:pre . 't', 'omnisharp_type_lookup') 35 | call s:map('n', s:pre . 'd', 'omnisharp_documentation') 36 | 37 | call s:map('n', s:pre . 'fs', 'omnisharp_find_symbol') 38 | call s:map('n', s:pre . 'ft', 'omnisharp_find_type') 39 | 40 | call s:map('n', s:pre . 'fx', 'omnisharp_fix_usings') 41 | 42 | call s:map('n', '', 'omnisharp_signature_help') 43 | call s:map('i', '', 'omnisharp_signature_help') 44 | 45 | call s:map('n', '[[', 'omnisharp_navigate_up') 46 | call s:map('n', ']]', 'omnisharp_navigate_down') 47 | 48 | call s:map('n', s:pre . 'gcc', 'omnisharp_global_code_check') 49 | 50 | call s:map('n', s:pre . 'hi', 'omnisharp_highlight_types') 51 | 52 | call s:map('n', s:pre . 'ca', 'omnisharp_code_actions') 53 | call s:map('x', s:pre . 'ca', 'omnisharp_code_actions') 54 | call s:map('n', s:pre . '.', 'omnisharp_code_action_repeat') 55 | call s:map('x', s:pre . '.', 'omnisharp_code_action_repeat') 56 | 57 | call s:map('n', s:pre . 'nm', 'omnisharp_rename') 58 | 59 | call s:map('n', s:pre . '=', 'omnisharp_code_format') 60 | 61 | call s:map('n', s:pre . 're', 'omnisharp_restart_server') 62 | call s:map('n', s:pre . 'st', 'omnisharp_start_server') 63 | call s:map('n', s:pre . 'sp', 'omnisharp_stop_server') 64 | 65 | call s:map('n', s:pre . 'rt', 'omnisharp_run_test') 66 | call s:map('n', s:pre . 'rnt', 'omnisharp_run_test_no_build') 67 | call s:map('n', s:pre . 'rat', 'omnisharp_run_tests_in_file') 68 | call s:map('n', s:pre . 'rant', 'omnisharp_run_tests_in_file_no_build') 69 | call s:map('n', s:pre . 'rdt', 'omnisharp_debug_test') 70 | call s:map('n', s:pre . 'rdnt', 'omnisharp_debug_test_no_build') 71 | endif 72 | 73 | if get(g:, 'sharpenup_map_legacy_csproj_actions', 1) 74 | call s:map('n', s:pre . 'xa', 'sharpenup_add_to_csproj') 75 | call s:map('n', s:pre . 'xr', 'sharpenup_rename_in_csproj') 76 | endif 77 | 78 | if g:sharpenup_codeactions 79 | if g:sharpenup_codeactions_set_signcolumn 80 | setlocal signcolumn=yes 81 | let b:undo_ftplugin .= '| setlocal signcolumn<' 82 | endif 83 | 84 | augroup sharpenup_ftplugin 85 | autocmd! * 86 | for au in split(g:sharpenup_codeactions_autocmd, ',') 87 | execute 'autocmd' au ' call sharpenup#codeactions#Count()' 88 | endfor 89 | augroup END 90 | 91 | let b:undo_ftplugin .= '| execute "autocmd! sharpenup_ftplugin * "' 92 | endif 93 | 94 | let &cpoptions = s:save_cpo 95 | unlet s:save_cpo 96 | 97 | " vim:et:sw=2:sts=2 98 | -------------------------------------------------------------------------------- /plugin/sharpenup.vim: -------------------------------------------------------------------------------- 1 | if exists('g:sharpenup_loaded') | finish | endif 2 | let g:sharpenup_loaded = 1 3 | 4 | scriptencoding utf-8 5 | 6 | let g:sharpenup_codeactions = 7 | \ get(g:, 'sharpenup_codeactions', exists('+signcolumn')) 8 | let g:sharpenup_codeactions_autocmd = 9 | \ get(g:, 'sharpenup_codeactions_autocmd', 'CursorHold') 10 | let g:sharpenup_codeactions_glyph = 11 | \ get(g:, 'sharpenup_codeactions_glyph', '💡') 12 | let g:sharpenup_codeactions_set_signcolumn = 13 | \ get(g:, 'sharpenup_codeactions_set_signcolumn', 1) 14 | 15 | if g:sharpenup_codeactions 16 | execute 'sign define sharpenup_CodeActions text=' . 17 | \ g:sharpenup_codeactions_glyph 18 | endif 19 | 20 | " Default highlight groups for sharpenup#statusline#Build() 21 | highlight default link SharpenUpLoading WarningMsg 22 | highlight default link SharpenUpReady Directory 23 | highlight default link SharpenUpDead NonText 24 | 25 | " vim:et:sw=2:sts=2 26 | --------------------------------------------------------------------------------