├── .gitignore ├── LICENSE ├── README.md └── plugin └── scrollstatus.vim /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 2-Clause License 2 | 3 | Copyright (c) 2020, Olivier Roques 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vim-scrollstatus 2 | 3 | A scrollbar for Vim statusline. For Neovim, check out 4 | [nvim-scrollbar](https://github.com/ojroques/nvim-scrollbar). 5 | 6 | ![demo](https://user-images.githubusercontent.com/23409060/188604635-0971e70b-f58e-4bc9-91ce-7ac0f0b496cb.gif) 7 | 8 | ## Installation 9 | With [vim-plug](https://github.com/junegunn/vim-plug): 10 | ```vim 11 | call plug#begin() 12 | Plug 'ojroques/vim-scrollstatus' 13 | call plug#end() 14 | ``` 15 | 16 | ## Usage 17 | With [vim-airline](https://github.com/vim-airline/vim-airline): 18 | ```vim 19 | let g:airline_section_x = '%{ScrollStatus()}' 20 | ``` 21 | 22 | With [lightline.vim](https://github.com/itchyny/lightline.vim): 23 | ```vim 24 | let g:lightline = { 25 | \ 'active': { 26 | \ 'right': [['lineinfo'], ['percent'], ['fileformat', 'fileencoding', 'filetype', 'charvaluehex']] 27 | \ }, 28 | \ 'component_function': {'percent': 'ScrollStatus'}, 29 | \ } 30 | ``` 31 | 32 | ## Configuration 33 | By default the scrollbar is 20 characters long. You can set another value with: 34 | ```vim 35 | let g:scrollstatus_size = 12 36 | ``` 37 | 38 | By default the symbols are set to `░` for the track and `█` for the bar. To change them: 39 | ```vim 40 | let g:scrollstatus_symbol_track = '-' 41 | let g:scrollstatus_symbol_bar = '|' 42 | ``` 43 | 44 | ## Example 45 | To reproduce the statusline from the screenshot: 46 | ```vim 47 | call plug#begin() 48 | Plug 'vim-airline/vim-airline' 49 | Plug 'ojroques/vim-scrollstatus' 50 | call plug#end() 51 | 52 | let g:airline_section_x = '%{ScrollStatus()} ' 53 | let g:airline_section_y = airline#section#create_right(['filetype']) 54 | let g:airline_section_z = airline#section#create([ 55 | \ '%#__accent_bold#%3l%#__restore__#/%L', ' ', 56 | \ '%#__accent_bold#%3v%#__restore__#/%3{virtcol("$") - 1}', 57 | \ ]) 58 | ``` 59 | -------------------------------------------------------------------------------- /plugin/scrollstatus.vim: -------------------------------------------------------------------------------- 1 | " vim-scrollstatus 2 | " By Olivier Roques 3 | " github.com/ojroques 4 | 5 | scriptencoding utf-8 6 | 7 | if exists('g:loaded_scrollstatus') || &compatible 8 | finish 9 | endif 10 | 11 | let g:loaded_scrollstatus = 1 12 | 13 | function! s:init() abort 14 | let s:size = get(g:, 'scrollstatus_size', 20) 15 | let s:symbol_track = get(g:, 'scrollstatus_symbol_track', '░') 16 | let s:symbol_bar = get(g:, 'scrollstatus_symbol_bar', '█') 17 | 18 | let s:numberLines = -1 19 | let s:firstVisibleLine = -1 20 | let s:lastVisibleLine = -1 21 | let s:numberVisibleLines = -1 22 | 23 | let s:binSize = 0 24 | let s:binBarStart = 0 25 | let s:barSize = 0 26 | 27 | let s:scrollStatus = [] 28 | 29 | for i in range(s:size) 30 | call add(s:scrollStatus, s:symbol_track) 31 | endfor 32 | endfunction 33 | 34 | function! s:getBinSize(numberLines, containerSize) abort 35 | let l:binSize = float2nr(round(floor(a:numberLines) / a:containerSize)) 36 | 37 | if l:binSize < 1 38 | return 1 39 | endif 40 | 41 | return l:binSize 42 | endfunction 43 | 44 | function! s:getBin(binSize, line, containerSize) abort 45 | let l:bin = a:line / a:binSize 46 | 47 | if l:bin > a:containerSize -1 48 | return a:containerSize - 1 49 | endif 50 | 51 | return l:bin 52 | endfunction 53 | 54 | function! s:getBarSize(numberLines, numberVisibleLines, containerSize) abort 55 | return float2nr(round(floor(a:numberVisibleLines * a:containerSize) / a:numberLines)) 56 | endfunction 57 | 58 | function! s:isSameNumberLines() abort 59 | return line('$') == s:numberLines 60 | endfunction 61 | 62 | function! s:isSameWindow() abort 63 | return line('w0') - 1 == s:firstVisibleLine && 64 | \ line('w$') - 1 == s:lastVisibleLine 65 | endfunction 66 | 67 | function! s:fillBar(binBarStart, barSize, symbol) abort 68 | for i in range(a:binBarStart, a:binBarStart + a:barSize) 69 | if i > s:size - 1 70 | break 71 | endif 72 | 73 | let s:scrollStatus[i] = a:symbol 74 | endfor 75 | endfunction 76 | 77 | function! ScrollStatus() abort 78 | if s:size <= 0 79 | finish 80 | endif 81 | 82 | if line('w$') < line('w0') 83 | return join(s:scrollStatus, '') 84 | endif 85 | 86 | if s:isSameNumberLines() && s:isSameWindow() 87 | return join(s:scrollStatus, '') 88 | endif 89 | 90 | if !s:isSameNumberLines() 91 | let s:numberLines = line('$') 92 | let s:binSize = s:getBinSize(s:numberLines, s:size) 93 | endif 94 | 95 | if !s:isSameWindow() 96 | let s:firstVisibleLine = line('w0') - 1 97 | let s:lastVisibleLine = line('w$') - 1 98 | let s:numberVisibleLines = s:lastVisibleLine - s:firstVisibleLine + 1 99 | endif 100 | 101 | call s:fillBar(s:binBarStart, s:barSize, s:symbol_track) 102 | 103 | let s:binBarStart = s:getBin(s:binSize, s:firstVisibleLine, s:size) 104 | let s:barSize = s:getBarSize(s:numberLines, s:numberVisibleLines, s:size) 105 | 106 | call s:fillBar(s:binBarStart, s:barSize, s:symbol_bar) 107 | 108 | return join(s:scrollStatus, '') 109 | endfunction 110 | 111 | call s:init() 112 | --------------------------------------------------------------------------------