├── README.rst └── plugin └── autoread.vim /README.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | vim-autoread 3 | ============ 4 | 5 | Automatically causes vim to reload files which have been written on disk but not 6 | modified in the buffer since the last write from vim. This enables a file open in 7 | vim to be edited using another application and saved. Upon returning to vim, 8 | as long as you haven't modified the file since the last change, the file will be 9 | automatically updated to reflect the changes made on disk, as though you had pressed 10 | :e manually. 11 | 12 | This is a bundled form of this script_ in order to be fetchable by Vundle_. 13 | 14 | .. _script: http://vim.wikia.com/wiki/Have_Vim_check_automatically_if_the_file_has_changed_externally 15 | .. _Vundle: https://github.com/gmarik/vundle 16 | 17 | 18 | Installation 19 | ============ 20 | 21 | Place in your vim plugins folder or add to your .vimrc:: 22 | 23 | Bundle 'djoshea/vim-autoread' 24 | -------------------------------------------------------------------------------- /plugin/autoread.vim: -------------------------------------------------------------------------------- 1 | " If you are using a console version of Vim, or dealing 2 | " with a file that changes externally (e.g. a web server log) 3 | " then Vim does not always check to see if the file has been changed. 4 | " The GUI version of Vim will check more often (for example on Focus change), 5 | " and prompt you if you want to reload the file. 6 | " 7 | " There can be cases where you can be working away, and Vim does not 8 | " realize the file has changed. This command will force Vim to check 9 | " more often. 10 | " 11 | " Calling this command sets up autocommands that check to see if the 12 | " current buffer has been modified outside of vim (using checktime) 13 | " and, if it has, reload it for you. 14 | " 15 | " This check is done whenever any of the following events are triggered: 16 | " * BufEnter 17 | " * CursorMoved 18 | " * CursorMovedI 19 | " * CursorHold 20 | " * CursorHoldI 21 | " 22 | " In other words, this check occurs whenever you enter a buffer, move the cursor, 23 | " or just wait without doing anything for 'updatetime' milliseconds. 24 | " 25 | " Normally it will ask you if you want to load the file, even if you haven't made 26 | " any changes in vim. This can get annoying, however, if you frequently need to reload 27 | " the file, so if you would rather have it to reload the buffer *without* 28 | " prompting you, add a bang (!) after the command (WatchForChanges!). 29 | " This will set the autoread option for that buffer in addition to setting up the 30 | " autocommands. 31 | " 32 | " If you want to turn *off* watching for the buffer, just call the command again while 33 | " in the same buffer. Each time you call the command it will toggle between on and off. 34 | " 35 | " WatchForChanges sets autocommands that are triggered while in *any* buffer. 36 | " If you want vim to only check for changes to that buffer while editing the buffer 37 | " that is being watched, use WatchForChangesWhileInThisBuffer instead. 38 | " 39 | command! -bang WatchForChanges :call WatchForChanges(@%, {'toggle': 1, 'autoread': 0}) 40 | command! -bang WatchForChangesWhileInThisBuffer :call WatchForChanges(@%, {'toggle': 1, 'autoread': 0, 'while_in_this_buffer_only': 1}) 41 | command! -bang WatchForChangesAllFile :call WatchForChanges('*', {'toggle': 1, 'autoread': 0}) 42 | 43 | " WatchForChanges function 44 | " 45 | " This is used by the WatchForChanges* commands, but it can also be 46 | " useful to call this from scripts. For example, if your script executes a 47 | " long-running process, you can have your script run that long-running process 48 | " in the background so that you can continue editing other files, redirects its 49 | " output to a file, and open the file in another buffer that keeps reloading itself 50 | " as more output from the long-running command becomes available. 51 | " 52 | " Arguments: 53 | " * bufname: The name of the buffer/file to watch for changes. 54 | " Use '*' to watch all files. 55 | " * options (optional): A Dict object with any of the following keys: 56 | " * autoread: If set to 1, causes autoread option to be turned on for the buffer in 57 | " addition to setting up the autocommands. 58 | " * toggle: If set to 1, causes this behavior to toggle between on and off. 59 | " Mostly useful for mappings and commands. In scripts, you probably want to 60 | " explicitly enable or disable it. 61 | " * disable: If set to 1, turns off this behavior (removes the autocommand group). 62 | " * while_in_this_buffer_only: If set to 0 (default), the events will be triggered no matter which 63 | " buffer you are editing. (Only the specified buffer will be checked for changes, 64 | " though, still.) If set to 1, the events will only be triggered while 65 | " editing the specified buffer. 66 | " * more_events: If set to 1 (the default), creates autocommands for the events 67 | " listed above. Set to 0 to not create autocommands for CursorMoved, CursorMovedI, 68 | " (Presumably, having too much going on for those events could slow things down, 69 | " since they are triggered so frequently...) 70 | function! WatchForChanges(bufname, ...) 71 | let s:timer = 0 " init timer for checking for updates even when Buffer is not in focus 72 | 73 | " Figure out which options are in effect 74 | if a:bufname == '*' 75 | let id = 'WatchForChanges'.'AnyBuffer' 76 | " If you try to do checktime *, you'll get E93: More than one match for * is given 77 | let bufspec = '' 78 | else 79 | if bufnr(a:bufname) == -1 80 | echoerr "Buffer " . a:bufname . " doesn't exist" 81 | return 82 | end 83 | let id = 'WatchForChanges'.bufnr(a:bufname) 84 | let bufspec = a:bufname 85 | end 86 | 87 | 88 | 89 | if len(a:000) == 0 90 | let options = {} 91 | else 92 | if type(a:1) == type({}) 93 | let options = a:1 94 | else 95 | echoerr "Argument must be a Dict" 96 | end 97 | end 98 | let autoread = has_key(options, 'autoread') ? options['autoread'] : 0 99 | let toggle = has_key(options, 'toggle') ? options['toggle'] : 0 100 | let disable = has_key(options, 'disable') ? options['disable'] : 0 101 | let more_events = has_key(options, 'more_events') ? options['more_events'] : 1 102 | let while_in_this_buffer_only = has_key(options, 'while_in_this_buffer_only') ? options['while_in_this_buffer_only'] : 0 103 | let check_interval = has_key(options, 'check_interval') ? options['check_interval'] : 500 104 | 105 | if while_in_this_buffer_only 106 | let event_bufspec = a:bufname 107 | else 108 | let event_bufspec = '*' 109 | end 110 | 111 | let reg_saved = @" 112 | "let autoread_saved = &autoread 113 | let msg = "\n" 114 | 115 | " Check to see if the autocommand already exists 116 | redir @" 117 | silent! exec 'au '.id 118 | redir END 119 | let l:defined = (@" !~ 'E216: No such group or event:') 120 | 121 | " If not yet defined... 122 | if !l:defined 123 | if l:autoread 124 | let msg = msg . 'Autoread enabled - ' 125 | if a:bufname == '*' 126 | set autoread 127 | else 128 | setlocal autoread 129 | end 130 | end 131 | silent! exec 'augroup '.id 132 | if a:bufname != '*' 133 | "exec "au BufDelete ".a:bufname . " :silent! au! ".id . " | silent! augroup! ".id 134 | "exec "au BufDelete ".a:bufname . " :echomsg 'Removing autocommands for ".id."' | au! ".id . " | augroup! ".id 135 | exec "au BufDelete ".a:bufname . " execute 'au! ".id."' | execute 'augroup! ".id."'" 136 | end 137 | exec "au BufEnter ".event_bufspec . " :silent! checktime ".bufspec 138 | exec "au CursorHold ".event_bufspec . " :silent! checktime ".bufspec 139 | exec "au CursorHoldI ".event_bufspec . " :silent! checktime ".bufspec 140 | 141 | " The following events might slow things down so we provide a way to disable them... 142 | " vim docs warn: 143 | " Careful: Don't do anything that the user does 144 | " not expect or that is slow. 145 | if more_events 146 | exec "au CursorMoved ".event_bufspec . " :silent! checktime ".bufspec 147 | exec "au CursorMovedI ".event_bufspec . " :silent! checktime ".bufspec 148 | end 149 | augroup END 150 | if s:timer != 0 151 | call timer_stop(s:timer) 152 | endif 153 | let s:timer = timer_start(check_interval, {-> execute('silent! checktime ' . bufspec)}, {'repeat': -1}) 154 | let msg = msg . 'Now watching ' . bufspec . ' for external updates...' 155 | end 156 | 157 | " If they want to disable it, or it is defined and they want to toggle it, 158 | if l:disable || (l:toggle && l:defined) 159 | if l:autoread 160 | let msg = msg . 'Autoread disabled - ' 161 | if a:bufname == '*' 162 | set noautoread 163 | else 164 | setlocal noautoread 165 | end 166 | end 167 | " Using an autogroup allows us to remove it easily with the following 168 | " command. If we do not use an autogroup, we cannot remove this 169 | " single :checktime command 170 | " augroup! checkforupdates 171 | silent! exec 'au! '.id 172 | silent! exec 'augroup! '.id 173 | let msg = msg . 'No longer watching ' . bufspec . ' for external updates.' 174 | elseif l:defined 175 | let msg = msg . 'Already watching ' . bufspec . ' for external updates' 176 | end 177 | 178 | "echo msg 179 | let @"=reg_saved 180 | endfunction 181 | 182 | autocmd VimEnter * WatchForChangesAllFile! 183 | 184 | --------------------------------------------------------------------------------