Skip to content

Commit

Permalink
Debounce key-presses to improve responsiveness
Browse files Browse the repository at this point in the history
This idea is based on a patch from Yiding Jia, with some additional
logic added to ensure that potentially expensive matching only occurs
when really needed (ie. we don't re-match just because you hit a cursor
up or down key).

Not sure what the sweet spot for the debounce interval is, so starting
with 50ms, and making it configurable. I suspect that on really large
hierarchies you might want this to be higher (say, 100, 150 or even
200ms) in order to reduce the likelihood of unwanted match computations
kicking off just because you happened to slow a little in typing.

Note the use of augroups here to ensure that we don't keep adding more
and more autocmds to the buffer (depending on the platform, the buffer
will be cleaned up with bwipeout! or bunload!; in practice the same
buffer is usually used over and over again, so we wind up with a single
autocmd assigned to a buffer designated as `<buffer=2>` or similar).

Signed-off-by: Wincent Colaiuta <win@wincent.com>
  • Loading branch information
wincent committed Jan 25, 2014
1 parent f9d168c commit ff72bd9
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 28 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright 2010-2012 Wincent Colaiuta. All rights reserved.
Copyright 2010-2014 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Expand Down
35 changes: 24 additions & 11 deletions doc/command-t.txt
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,14 @@ Following is a list of all available options:
If set to 0, the window will occupy as much of the available space as
needed to show matching entries.

*g:CommandTInputDebounce*
|g:CommandTInputDebounce| number (default: 50)

The number of milliseconds to wait before updating the match listing
following a key-press. This can be used to avoid wasteful recomputation
when making a rapid series of key-presses in a directory with many tens
(or hundreds) of thousands of files.

*g:CommandTMinHeight*
|g:CommandTMinHeight| number (default: 0)

Expand Down Expand Up @@ -677,16 +685,16 @@ Command-T is written and maintained by Wincent Colaiuta <win@wincent.com>.
Other contributors that have submitted patches include (in alphabetical
order):

Andy Waite Matthew Todd Steven Moazami
Anthony Panozzo Mike Lundy Sung Pae
Daniel Hahler Nate Kane Thomas Pelletier
Felix Tjandrawibawa Nicholas Alpi Victor Hugo Borja
Gary Bernhardt Nadav Samet Vít Ondruch
Ivan Ukhov Noon Silk Woody Peterson
Jeff Kreeftmeijer Paul Jolly Yan Pritzker
Lucas de Vries Rainux Luo Zak Johnson
Marcus Brito Scott Bronson
Marian Schubert Seth Fowler
Andy Waite Matthew Todd Steven Moazami
Anthony Panozzo Mike Lundy Sung Pae
Daniel Hahler Nadav Samet Thomas Pelletier
Felix Tjandrawibawa Nate Kane Victor Hugo Borja
Gary Bernhardt Nicholas Alpi Vít Ondruch
Ivan Ukhov Noon Silk Woody Peterson
Jeff Kreeftmeijer Paul Jolly Yan Pritzker
Lucas de Vries Rainux Luo Yiding Jia
Marcus Brito Scott Bronson Zak Johnson
Marian Schubert Seth Fowler

As this was the first Vim plug-in I had ever written I was heavily influenced
by the design of the LustyExplorer plug-in by Stephen Bach, which I understand
Expand Down Expand Up @@ -764,7 +772,7 @@ PayPal to win@wincent.com:

LICENSE *command-t-license*

Copyright 2010-2013 Wincent Colaiuta. All rights reserved.
Copyright 2010-2014 Wincent Colaiuta. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
Expand All @@ -789,6 +797,11 @@ POSSIBILITY OF SUCH DAMAGE.

HISTORY *command-t-history*

1.7 (unreleased)

- added |g:CommandTInputDebounce|, which can be used to improve responsiveness
in large file hierarchies (based on patch from Yiding Jia)

1.6.1 (22 December 2013)

- defer processor count detection until runtime (makes it possible to sensibly
Expand Down
6 changes: 5 additions & 1 deletion plugin/command-t.vim
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
" command-t.vim
" Copyright 2010-2013 Wincent Colaiuta. All rights reserved.
" Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
"
" Redistribution and use in source and binary forms, with or without
" modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -92,6 +92,10 @@ if !has('ruby')
finish
endif

function CommandTListMatches()
ruby $command_t.list_matches
endfunction

function CommandTHandleKey(arg)
ruby $command_t.handle_key
endfunction
Expand Down
49 changes: 34 additions & 15 deletions ruby/command-t/controller.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2010-2013 Wincent Colaiuta. All rights reserved.
# Copyright 2010-2014 Wincent Colaiuta. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
Expand Down Expand Up @@ -95,7 +95,7 @@ def quickfix
def refresh
return unless @active_finder && @active_finder.respond_to?(:flush)
@active_finder.flush
list_matches
list_matches!
end

def flush
Expand All @@ -109,7 +109,7 @@ def handle_key
key = ::VIM::evaluate('a:arg').to_i.chr
if @focus == @prompt
@prompt.add! key
list_matches
@needs_update = true
else
@match_window.find key
end
Expand All @@ -118,14 +118,14 @@ def handle_key
def backspace
if @focus == @prompt
@prompt.backspace!
list_matches
@needs_update = true
end
end

def delete
if @focus == @prompt
@prompt.delete!
list_matches
@needs_update.true
end
end

Expand Down Expand Up @@ -155,7 +155,7 @@ def select_prev

def clear
@prompt.clear!
list_matches
list_matches!
end

def cursor_left
Expand All @@ -182,8 +182,25 @@ def unload
@match_window.unload
end

def list_matches(options = {})
return unless @needs_update || options[:force]

@matches = @active_finder.sorted_matches_for(
@prompt.abbrev,
:limit => match_limit,
:threads => CommandT::Util.processor_count
)
@match_window.matches = @matches

@needs_update = false
end

private

def list_matches!
list_matches(:force => true)
end

def show
@initial_window = $curwin
@initial_buffer = $curbuf
Expand All @@ -196,6 +213,7 @@ def show
@focus = @prompt
@prompt.focus
register_for_key_presses
set_up_autocmds
clear # clears prompt and lists matches
end

Expand Down Expand Up @@ -333,6 +351,16 @@ def register_for_key_presses
end
end

def set_up_autocmds
debounce_interval = get_number('g:CommandTInputDebounce') || 50

::VIM::command 'augroup Command-T'
::VIM::command 'au!'
::VIM::command 'autocmd CursorHold <buffer> :call CommandTListMatches()'
::VIM::command "setlocal updatetime=#{debounce_interval}"
::VIM::command 'augroup END'
end

# Returns the desired maximum number of matches, based on available
# vertical space and the g:CommandTMaxHeight option.
def match_limit
Expand All @@ -342,15 +370,6 @@ def match_limit
limit
end

def list_matches
@matches = @active_finder.sorted_matches_for(
@prompt.abbrev,
:limit => match_limit,
:threads => CommandT::Util.processor_count
)
@match_window.matches = @matches
end

def buffer_finder
@buffer_finder ||= CommandT::BufferFinder.new
end
Expand Down

0 comments on commit ff72bd9

Please sign in to comment.