diff --git a/fzf b/fzf index 2bce1bc..fd8172d 100755 --- a/fzf +++ b/fzf @@ -105,7 +105,7 @@ when /darwin/ end def self.nfc str, offset - ret = '' + ret = '' omap = [] pend = [] str.split(//).each_with_index do |c, idx| @@ -198,7 +198,7 @@ def print_info progress = true, msg = nil end def refresh - C.setpos cursor_y, 2 + ulen(@query[0, @cursor_x]) + C.setpos cursor_y, 2 + width(@query[0, @cursor_x]) C.refresh end @@ -207,12 +207,12 @@ def ctrl char end if RUBY_VERSION.split('.').map { |e| e.rjust(3, '0') }.join > '001009' - def ulen str + def width str @urx ||= Regexp.new '\p{Han}|\p{Katakana}|\p{Hiragana}|\p{Hangul}' str.gsub(@urx, ' ').length end else - def ulen str + def width str str.length end @@ -334,6 +334,8 @@ searcher = Thread.new { new_search = events[:key] || events[:new] user_input = events[:key] || events[:vcursor] + progress = 0 + started_at = Time.now if new_search && !@lists.empty? events.delete :new @@ -346,19 +348,26 @@ searcher = Thread.new { matches = fcache[q] ||= begin - @smtx.synchronize do - print_info true, ' ..' - print_input - refresh - end unless q.empty? - found = [] skip = false + cnt = 0 @lists.each do |pair| - @mtx.synchronize { skip = @events[:key] } + list, cache = pair + cnt += list.length + + @mtx.synchronize { + skip = @events[:key] + progress = (100 * cnt / @count) + } break if skip - list, cache = pair + if !q.empty? && progress < 100 && Time.now - started_at > 0.5 + @smtx.synchronize do + print_info true, " (#{progress}%)" + refresh + end + end + found.concat(cache[q] ||= begin prefix, suffix = @query[0, @cursor_x], @query[@cursor_x..-1] || '' prefix_cache = suffix_cache = nil @@ -397,7 +406,7 @@ searcher = Thread.new { end#new_search # This small delay reduces the number of partial lists - sleep [20, delay += 5].min * 0.01 unless user_input + sleep((delay = [20, delay + 5].min) * 0.01) unless user_input if events.delete(:vcursor) || new_search @mtx.synchronize do @@ -417,7 +426,7 @@ searcher = Thread.new { end end - maxc = C.cols - 5 + maxc = C.cols - 3 matches[0, max_items].each_with_index do |item, idx| next if !new_search && !((vcursor-1)..(vcursor+1)).include?(idx) @@ -426,19 +435,28 @@ searcher = Thread.new { chosen = idx == vcursor b, e = offset - if line.length > maxc - diff = e - (maxc - 2) - if diff > 2 - line = '..' + line[diff..-1] - b -= diff - 2 - b = [2, b].max + # Overflow + if width(line) > maxc + ewidth = width(line[0...e]) + # Stri.. + if ewidth <= maxc + line = line[0...-1] while width(line) > maxc - 2 + line << '..' + # ..ring else - line = line[0, maxc] + '..' + # ..ri.. + line = line[0...e] + '..' if ewidth < width(line) - 2 + while width(line) > maxc - 2 + b -= 1 + e -= 1 + line = line[1..-1] + end + b += 2 + e += 2 + b = [2, b].max + line = '..' + line end end - if line.length > maxc - line = line[0, maxc] + '..' - end C.setpos row, 0 C.clrtoeol @@ -447,8 +465,7 @@ searcher = Thread.new { C.attron color(:chosen, true) if chosen - e = [e, maxc].min - if b < maxc && b < e + if b < e C.addstr line[0, b] cprint line[b...e], color(chosen ? :match! : :match, chosen) C.attron color(:chosen, true) if chosen