Compare commits

..

53 Commits
0.1.0 ... 0.4.0

Author SHA1 Message Date
Junegunn Choi
be3b948034 Fix Gem executable 2013-11-17 01:37:56 +09:00
Junegunn Choi
93dafff424 Implement ALT-B / ALT-F 2013-11-17 01:19:16 +09:00
Junegunn Choi
419bc17c0c Refactoring: separate renderer thread 2013-11-17 00:05:42 +09:00
Junegunn Choi
f0a5757244 Different color for selection-marker 2013-11-16 18:19:26 +09:00
Junegunn Choi
f0b2b98c5d Increase FZF_DEFAULT_SORT to 1000 2013-11-16 11:51:18 +09:00
Junegunn Choi
4530819539 Update README 2013-11-16 02:21:39 +09:00
Junegunn Choi
1825a73e2e "Extended-search mode" 2013-11-16 02:20:40 +09:00
Junegunn Choi
30d4974509 Update README 2013-11-16 01:55:33 +09:00
Junegunn Choi
e4a49dbb2a Add exact-match and invert-exact-match match types 2013-11-16 00:58:46 +09:00
Junegunn Choi
76c7f4f9c0 Do not include highlighted item when items chosen 2013-11-16 00:31:22 +09:00
Junegunn Choi
8ae604af67 Merge branch 'devel' 2013-11-16 00:13:04 +09:00
Junegunn Choi
6037e1e217 Ignore invalid UTF-8 sequences 2013-11-15 21:49:00 +09:00
Junegunn Choi
43acf5c8a4 Extended mode
- Implement prefix caching of extended mode
- Improved ranking algorithm for extended mode
- Fix nfc conversion bug
2013-11-15 20:40:57 +09:00
Junegunn Choi
545e8bfcee Prototype implementation of extended mode (#1) 2013-11-15 02:13:18 +09:00
Junegunn Choi
90ad6d50b8 Refactoring for test 2013-11-15 01:32:42 +09:00
Junegunn Choi
67bdc3a0ad Allow multiple highlighted regions 2013-11-14 20:04:46 +09:00
Junegunn Choi
ff34c6b272 Merge pull request #5 from Vifon/zsh-widgets
new zsh widgets
2013-11-10 16:11:29 -08:00
Wojciech Siewierski
b2ac52462c zsh widget fix
* fzf-cd-widget properly escapes the special characters
2013-11-10 18:57:47 +01:00
Wojciech Siewierski
a6f7caf20d new zsh widgets
+ new fzf-cd-widget for running cd

* fzf-file-widget now properly escapes the special characters and supports
  multi-selection

* fzf-history-widget replaces the current line instead of appending to it
2013-11-10 18:28:59 +01:00
Junegunn Choi
1e9e597837 Merge pull request #4 from Vifon/patch-1
superfluous backslash in zle widget removed
2013-11-10 06:34:21 -08:00
Wojciech Siewierski
0dc725d09c superfluous backslash in zle widget removed 2013-11-10 15:31:10 +01:00
Junegunn Choi
1eceb6a4b9 FZF_DEFAULT_SORT 2013-11-10 20:22:57 +09:00
Junegunn Choi
8777a495bc Shift-TAB on multi-select mode 2013-11-10 20:19:57 +09:00
Junegunn Choi
83825dbbd3 Add Tips section 2013-11-10 20:03:38 +09:00
Junegunn Choi
1ac19a2097 Update README 2013-11-10 11:53:13 +09:00
Junegunn Choi
833c6e1eeb Update example 2013-11-10 04:00:27 +09:00
Junegunn Choi
8a0a3f9bf5 Do not sort the result if query is empty 2013-11-10 03:57:10 +09:00
Junegunn Choi
ddf6e5ef1e Implement multi-select mode (#3) 2013-11-10 03:56:18 +09:00
Junegunn Choi
11a1010e9e Add zsh widget examples 2013-11-09 01:16:39 +09:00
Junegunn Choi
75b666bf54 Update README (replace backticks with $())
As reported in #2, backticks on oh-my-zsh (with TERM=xterm*)
makes fzf run twice. This should be a bug of oh-my-zsh,
but for now using $() seems to be a quick workaround.
2013-11-06 20:54:02 +09:00
Junegunn Choi
3f73554a9e Fix FZF_DEFAULT_COMMAND 2013-11-05 21:05:34 +09:00
Junegunn Choi
dc67420319 Make fzf.vim separately installable 2013-11-05 13:45:23 +09:00
Junegunn Choi
f2d8e7e3ee Update README 2013-11-05 00:11:06 +09:00
Junegunn Choi
de8116b1cf Fix error on Linux with Ruby 1.8 2013-11-04 10:38:16 +09:00
Junegunn Choi
1460e0a10b 0.2.0 2013-11-03 22:51:00 +09:00
Junegunn Choi
c46dad465f Fix invalid return when query string is empty 2013-11-03 22:49:12 +09:00
Junegunn Choi
0df647b2a7 Strip null bytes in the string 2013-11-03 22:15:52 +09:00
Junegunn Choi
69d6b58f88 Do not block on --no-sort 2013-11-03 22:01:25 +09:00
Junegunn Choi
8e305edcf2 Add --no-color (+c) option 2013-11-03 11:45:14 +09:00
Junegunn Choi
c326e363eb Premature optimization is root of all fun 2013-11-03 10:43:48 +09:00
Junegunn Choi
d1298b8fff Reduce memory footprint 2013-11-03 04:05:32 +09:00
Junegunn Choi
2a0e0ded2a Remove Gemfile 2013-11-03 01:11:36 +09:00
Junegunn Choi
7cecf648eb Optimize left/right trimming 2013-11-03 00:06:50 +09:00
Junegunn Choi
c3c94ea889 Fix long item display 2013-11-02 20:58:23 +09:00
Junegunn Choi
94f0c3d22b Bump up gem version to 0.1.3 2013-11-02 20:41:29 +09:00
Junegunn Choi
d717096ee3 Update README 2013-11-02 20:40:25 +09:00
Junegunn Choi
1629fe079a Improve display
- CJK wide character support
- Progress reporting for long-running queries (> 0.5sec)
2013-11-02 20:12:39 +09:00
Junegunn Choi
6a9970c98e FZF_DEFAULT_COMMAND 2013-11-02 12:56:43 +09:00
Junegunn Choi
682583e88f 0.1.1 2013-11-01 16:13:12 +09:00
Junegunn Choi
fd2472d11c Ignore empty file path 2013-11-01 16:07:46 +09:00
Junegunn Choi
311c4a36e2 Remove initial delay 2013-11-01 02:02:00 +09:00
Junegunn Choi
b98fba4cf1 Gradually increase delay upto 0.2 seconds 2013-11-01 01:59:23 +09:00
Junegunn Choi
a03b5c8c42 gem install fzf 2013-11-01 01:12:46 +09:00
7 changed files with 1222 additions and 501 deletions

View File

@@ -1,4 +0,0 @@
source 'https://rubygems.org'
# Specify your gem's dependencies in fzf.gemspec
gemspec

139
README.md
View File

@@ -16,7 +16,8 @@ fzf requires Ruby (>= 1.8.5).
Installation Installation
------------ ------------
Download fzf executable and put it somewhere in your search $PATH. Download [fzf executable](https://raw.github.com/junegunn/fzf/master/fzf) and
put it somewhere in your search $PATH.
```sh ```sh
mkdir -p ~/bin mkdir -p ~/bin
@@ -38,15 +39,21 @@ Make sure that ~/bin is included in $PATH.
export PATH=$PATH:~/bin export PATH=$PATH:~/bin
``` ```
Install as Vim plugin ### Install as Ruby gem
---------------------
fzf was not designed to be a Vim plugin, but you can use it as one. The only fzf can be installed as a Ruby gem
reason one might consider using fzf in Vim is its speed. For a very large list
of files, fzf is significantly faster than native Vim plugins.
You can use any Vim plugin manager to install fzf as a Vim plugin. If you don't ```
use one, I recommend you try [vim-plug](https://github.com/junegunn/vim-plug). gem install fzf
```
It's a bit easier to install and update the script but the Ruby gem version
takes slightly longer to start.
### Install as Vim plugin
You can use any Vim plugin manager to install fzf for Vim. If you don't use one,
I recommend you try [vim-plug](https://github.com/junegunn/vim-plug).
1. [Install vim-plug](https://github.com/junegunn/vim-plug#usage) 1. [Install vim-plug](https://github.com/junegunn/vim-plug#usage)
2. Edit your .vimrc 2. Edit your .vimrc
@@ -64,9 +71,12 @@ Usage
``` ```
usage: fzf [options] usage: fzf [options]
-s, --sort=MAX Maximum number of matched items to sort. Default: 500 -m, --multi Enable multi-select
+s, --no-sort Keep the sequence unchanged. -x, --extended Extended-search mode
-s, --sort=MAX Maximum number of matched items to sort. Default: 1000
+s, --no-sort Do not sort the result. Keep the sequence unchanged.
+i Case-sensitive match +i Case-sensitive match
+c, --no-color Disable colors
``` ```
fzf will launch curses-based finder, read the list from STDIN, and write the fzf will launch curses-based finder, read the list from STDIN, and write the
@@ -77,10 +87,11 @@ find * -type f | fzf > selected
``` ```
Without STDIN pipe, fzf will use find command to fetch the list of Without STDIN pipe, fzf will use find command to fetch the list of
files (excluding hidden ones). files excluding hidden ones. (You can override the default command with
`FZF_DEFAULT_COMMAND`)
```sh ```sh
vim `fzf` vim $(fzf)
``` ```
If you want to preserve the exact sequence of the input, provide `--no-sort` (or If you want to preserve the exact sequence of the input, provide `--no-sort` (or
@@ -100,6 +111,26 @@ The following readline key bindings should also work as expected.
- CTRL-A / CTRL-E - CTRL-A / CTRL-E
- CTRL-B / CTRL-F - CTRL-B / CTRL-F
- CTRL-W / CTRL-U - CTRL-W / CTRL-U
- ALT-B / ALT-F
If you enable multi-select mode with `-m` option, you can select multiple items
with TAB or Shift-TAB key.
### Extended-search mode
With `-x` or `--extended` option, fzf will start in "extended-search mode".
In this mode, you can specify multiple patterns delimited by spaces,
such as: `^music .mp3$ sbtrkt !rmx`
| Token | Description | Match type |
| -------- | -------------------------------- | -------------------- |
| `^music` | Items that start with `music` | prefix-exact-match |
| `.mp3$` | Items that end with `.mp3` | suffix-exact-match |
| `sbtrkt` | Items that match `sbtrkt` | fuzzy-match |
| `!rmx` | Items that do not match `rmx` | inverse-fuzzy-match |
| `'wild` | Items that include `wild` | exact-match (quoted) |
| `!'fire` | Items that do not include `fire` | inverse-exact-match |
Usage as Vim plugin Usage as Vim plugin
------------------- -------------------
@@ -117,23 +148,27 @@ You can override the command which produces input to fzf.
let g:fzf_command = 'find . -type f' let g:fzf_command = 'find . -type f'
``` ```
Most of the time, you will prefer native Vim plugins with better integration
with Vim. The only reason one might consider using fzf in Vim is its speed. For
a very large list of files, fzf is significantly faster and it does not block.
Useful bash examples Useful bash examples
-------------------- --------------------
```sh ```sh
# vimf - Open selected file in Vim # vimf - Open selected file in Vim
vimf() { vimf() {
FILE=`fzf` && vim "$FILE" FILE=$(fzf) && vim "$FILE"
} }
# fd - cd to selected directory # fd - cd to selected directory
fd() { fd() {
DIR=`find ${1:-*} -path '*/\.*' -prune -o -type d -print 2> /dev/null | fzf` && cd "$DIR" DIR=$(find ${1:-*} -path '*/\.*' -prune -o -type d -print 2> /dev/null | fzf) && cd "$DIR"
} }
# fda - including hidden directories # fda - including hidden directories
fda() { fda() {
DIR=`find ${1:-*} -type d 2> /dev/null | fzf` && cd "$DIR" DIR=$(find ${1:-*} -type d 2> /dev/null | fzf) && cd "$DIR"
} }
# fh - repeat history # fh - repeat history
@@ -143,14 +178,84 @@ fh() {
# fkill - kill process # fkill - kill process
fkill() { fkill() {
ps -ef | sed 1d | fzf | awk '{print $2}' | xargs kill -${1:-9} ps -ef | sed 1d | fzf -m | awk '{print $2}' | xargs kill -${1:-9}
} }
# CTRL-T - Open fuzzy finder and paste the selected item to the command line # (Assuming you don't use the default CTRL-T and CTRL-R)
# CTRL-T - Paste the selected file path into the command line
bind '"\er": redraw-current-line' bind '"\er": redraw-current-line'
bind '"\C-t": " \C-u \C-a\C-k$(fzf)\e\C-e\C-y\C-a\C-y\ey\C-h\C-e\er"' bind '"\C-t": " \C-u \C-a\C-k$(fzf)\e\C-e\C-y\C-a\C-y\ey\C-h\C-e\er"'
# CTRL-R - Paste the selected command from history into the command line
bind '"\C-r": " \C-e\C-u$(history | fzf +s | sed \"s/ *[0-9]* *//\")\e\C-e\er"'
``` ```
zsh widgets
-----------
```sh
# CTRL-T - Paste the selected file(s) path into the command line
fzf-file-widget() {
local FILES
local IFS="
"
FILES=($(
find * -path '*/\.*' -prune \
-o -type f -print \
-o -type l -print 2> /dev/null | fzf -m))
unset IFS
FILES=$FILES:q
LBUFFER="${LBUFFER%% #} $FILES"
zle redisplay
}
zle -N fzf-file-widget
bindkey '^T' fzf-file-widget
# ALT-C - cd into the selected directory
fzf-cd-widget() {
cd "${$(find * -path '*/\.*' -prune \
-o -type d -print 2> /dev/null | fzf):-.}"
zle reset-prompt
}
zle -N fzf-cd-widget
bindkey '\ec' fzf-cd-widget
# CTRL-R - Paste the selected command from history into the command line
fzf-history-widget() {
LBUFFER=$(history | fzf +s | sed "s/ *[0-9]* *//")
zle redisplay
}
zle -N fzf-history-widget
bindkey '^R' fzf-history-widget
```
Tips
----
### Faster startup with `--disable-gems` options
If you're running Ruby 1.9 or above, you can improve the startup time with
`--disable-gems` option to Ruby.
- `time ruby ~/bin/fzf -h`
- 0.077 sec
- `time ruby --disable-gems ~/bin/fzf -h`
- 0.025 sec
Define fzf alias with the option as follows:
```sh
alias fzf='ruby --disable-gems ~/bin/fzf'
```
### Incorrect display on Ruby 1.8
It is reported that the output of fzf can become unreadable on some terminals
when it's running on Ruby 1.8. If you experience the problem, upgrade your Ruby
to 1.9 or above. Ruby 1.9 or above is also required for displaying Unicode
characters.
License License
------- -------

View File

@@ -1 +1,8 @@
require "bundler/gem_tasks" require "bundler/gem_tasks"
require 'rake/testtask'
Rake::TestTask.new(:test) do |test|
test.pattern = 'test/**/test_*.rb'
test.verbose = true
end

1257
fzf

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
# coding: utf-8 # coding: utf-8
Gem::Specification.new do |spec| Gem::Specification.new do |spec|
spec.name = 'fzf' spec.name = 'fzf'
spec.version = '0.1.0' spec.version = '0.4.0'
spec.authors = ['Junegunn Choi'] spec.authors = ['Junegunn Choi']
spec.email = ['junegunn.c@gmail.com'] spec.email = ['junegunn.c@gmail.com']
spec.description = %q{Fuzzy finder for your shell} spec.description = %q{Fuzzy finder for your shell}

View File

@@ -27,9 +27,13 @@ function! s:fzf(args)
try try
let tf = tempname() let tf = tempname()
let prefix = exists('g:fzf_command') ? g:fzf_command.'|' : '' let prefix = exists('g:fzf_command') ? g:fzf_command.'|' : ''
execute "silent !".prefix."/usr/bin/env ruby ".s:exec." ".a:args." > ".tf let fzf = executable(s:exec) ? s:exec : 'fzf'
execute "silent !".prefix.fzf." ".a:args." > ".tf
if !v:shell_error if !v:shell_error
execute 'silent e '.join(readfile(tf), '') let file = join(readfile(tf), '')
if !empty(file)
execute 'silent e '.file
endif
endif endif
finally finally
silent! call delete(tf) silent! call delete(tf)

306
test/test_fzf.rb Normal file
View File

@@ -0,0 +1,306 @@
#!/usr/bin/env ruby
# encoding: utf-8
require 'minitest/autorun'
$LOAD_PATH.unshift File.expand_path('../..', __FILE__)
ENV['FZF_EXECUTABLE'] = '0'
load 'fzf'
class TestFZF < MiniTest::Unit::TestCase
def test_default_options
fzf = FZF.new []
assert_equal 1000, fzf.sort
assert_equal false, fzf.multi
assert_equal true, fzf.color
assert_equal Regexp::IGNORECASE, fzf.rxflag
begin
ENV['FZF_DEFAULT_SORT'] = '1500'
fzf = FZF.new []
assert_equal 1500, fzf.sort
ensure
ENV.delete 'FZF_DEFAULT_SORT'
end
end
def test_option_parser
# Long opts
fzf = FZF.new %w[--sort=2000 --no-color --multi +i]
assert_equal 2000, fzf.sort
assert_equal true, fzf.multi
assert_equal false, fzf.color
assert_equal 0, fzf.rxflag
# Short opts
fzf = FZF.new %w[-s 2000 +c -m +i]
assert_equal 2000, fzf.sort
assert_equal true, fzf.multi
assert_equal false, fzf.color
assert_equal 0, fzf.rxflag
end
def test_invalid_option
[%w[-s 2000 +s], %w[yo dawg]].each do |argv|
assert_raises(SystemExit) do
fzf = FZF.new argv
end
end
end
# FIXME Only on 1.9 or above
def test_width
fzf = FZF.new []
assert_equal 5, fzf.width('abcde')
assert_equal 4, fzf.width('한글')
assert_equal 5, fzf.width('한글.')
end
def test_trim
fzf = FZF.new []
assert_equal ['사.', 6], fzf.trim('가나다라마바사.', 4, true)
assert_equal ['바사.', 5], fzf.trim('가나다라마바사.', 5, true)
assert_equal ['바사.', 5], fzf.trim('가나다라마바사.', 6, true)
assert_equal ['마바사.', 4], fzf.trim('가나다라마바사.', 7, true)
assert_equal ['가나', 6], fzf.trim('가나다라마바사.', 4, false)
assert_equal ['가나', 6], fzf.trim('가나다라마바사.', 5, false)
assert_equal ['가나a', 6], fzf.trim('가나ab라마바사.', 5, false)
assert_equal ['가나ab', 5], fzf.trim('가나ab라마바사.', 6, false)
assert_equal ['가나ab', 5], fzf.trim('가나ab라마바사.', 7, false)
end
def test_format
fzf = FZF.new []
assert_equal [['01234..', false]], fzf.format('0123456789', 7, [])
assert_equal [['012', false], ['34', true], ['..', false]],
fzf.format('0123456789', 7, [[3, 5]])
assert_equal [['..56', false], ['789', true]],
fzf.format('0123456789', 7, [[7, 10]])
assert_equal [['..56', false], ['78', true], ['9', false]],
fzf.format('0123456789', 7, [[7, 9]])
(3..5).each do |i|
assert_equal [['..', false], ['567', true], ['89', false]],
fzf.format('0123456789', 7, [[i, 8]])
end
assert_equal [['..', false], ['345', true], ['..', false]],
fzf.format('0123456789', 7, [[3, 6]])
assert_equal [['012', false], ['34', true], ['..', false]],
fzf.format('0123456789', 7, [[3, 5]])
# Multi-region
assert_equal [["0", true], ["1", false], ["2", true], ["34..", false]],
fzf.format('0123456789', 7, [[0, 1], [2, 3]])
assert_equal [["..", false], ["5", true], ["6", false], ["78", true], ["9", false]],
fzf.format('0123456789', 7, [[3, 6], [7, 9]])
assert_equal [["..", false], ["3", true], ["4", false], ["5", true], ["..", false]],
fzf.format('0123456789', 7, [[3, 4], [5, 6]])
# Multi-region Overlap
assert_equal [["..", false], ["345", true], ["..", false]],
fzf.format('0123456789', 7, [[4, 5], [3, 6]])
end
def test_fuzzy_matcher
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE
list = %w[
juice
juiceful
juiceless
juicily
juiciness
juicy]
assert matcher.caches.empty?
assert_equal(
[["juice", [[0, 1]]],
["juiceful", [[0, 1]]],
["juiceless", [[0, 1]]],
["juicily", [[0, 1]]],
["juiciness", [[0, 1]]],
["juicy", [[0, 1]]]], matcher.match(list, 'j', '', '').sort)
assert !matcher.caches.empty?
assert_equal [list.object_id], matcher.caches.keys
assert_equal 1, matcher.caches[list.object_id].length
assert_equal 6, matcher.caches[list.object_id]['j'].length
assert_equal(
[["juicily", [[0, 5]]],
["juiciness", [[0, 5]]]], matcher.match(list, 'jii', '', '').sort)
assert_equal(
[["juicily", [[2, 5]]],
["juiciness", [[2, 5]]]], matcher.match(list, 'ii', '', '').sort)
assert_equal 3, matcher.caches[list.object_id].length
assert_equal 2, matcher.caches[list.object_id]['ii'].length
# TODO : partial_cache
end
def test_fuzzy_matcher_case_sensitive
assert_equal [['Fruit', [[0, 5]]]],
FZF::FuzzyMatcher.new(0).match(%w[Fruit Grapefruit], 'Fruit', '', '').sort
assert_equal [["Fruit", [[0, 5]]], ["Grapefruit", [[5, 10]]]],
FZF::FuzzyMatcher.new(Regexp::IGNORECASE).
match(%w[Fruit Grapefruit], 'Fruit', '', '').sort
end
def test_extended_fuzzy_matcher
matcher = FZF::ExtendedFuzzyMatcher.new Regexp::IGNORECASE
list = %w[
juice
juiceful
juiceless
juicily
juiciness
juicy
_juice]
match = proc { |q, prefix|
matcher.match(list, q, prefix, '').sort.map { |p| [p.first, p.last.sort] }
}
assert matcher.caches.empty?
3.times do
['y j', 'j y'].each do |pat|
(0..pat.length - 1).each do |prefix_length|
prefix = pat[0, prefix_length]
assert_equal(
[["juicily", [[0, 1], [6, 7]]],
["juicy", [[0, 1], [4, 5]]]],
match.call(pat, prefix))
end
end
# $
assert_equal [["juiceful", [[7, 8]]]], match.call('l$', '')
assert_equal [["juiceful", [[7, 8]]],
["juiceless", [[5, 6]]],
["juicily", [[5, 6]]]], match.call('l', '')
# ^
assert_equal list.length, match.call('j', '').length
assert_equal list.length - 1, match.call('^j', '').length
# !
assert_equal 0, match.call('!j', '').length
# ! + ^
assert_equal [["_juice", []]], match.call('!^j', '')
# ! + $
assert_equal list.length - 1, match.call('!l$', '').length
# ! + f
assert_equal [["juicy", [[4, 5]]]], match.call('y !l', '')
# '
assert_equal %w[juiceful juiceless juicily],
match.call('il', '').map { |e| e.first }
assert_equal %w[juicily],
match.call("'il", '').map { |e| e.first }
assert_equal (list - %w[juicily]).sort,
match.call("!'il", '').map { |e| e.first }.sort
end
assert !matcher.caches.empty?
end
def test_xfuzzy_matcher_prefix_cache
matcher = FZF::ExtendedFuzzyMatcher.new Regexp::IGNORECASE
list = %w[
a.java
b.java
java.jive
c.java$
d.java
]
2.times do
assert_equal 5, matcher.match(list, 'java', 'java', '').length
assert_equal 3, matcher.match(list, 'java$', 'java$', '').length
assert_equal 1, matcher.match(list, 'java$$', 'java$$', '').length
assert_equal 0, matcher.match(list, '!java', '!java', '').length
assert_equal 4, matcher.match(list, '!^jav', '!^jav', '').length
assert_equal 4, matcher.match(list, '!^java', '!^java', '').length
assert_equal 2, matcher.match(list, '!^java !b !c', '!^java', '').length
end
end
def test_sort_by_rank
matcher = FZF::FuzzyMatcher.new Regexp::IGNORECASE
xmatcher = FZF::ExtendedFuzzyMatcher.new Regexp::IGNORECASE
list = %w[
0____1
0_____1
01
____0_1
01_
_01_
0______1
___01___
]
assert_equal(
[["01", [[0, 2]]],
["01_", [[0, 2]]],
["_01_", [[1, 3]]],
["___01___", [[3, 5]]],
["____0_1", [[4, 7]]],
["0____1", [[0, 6]]],
["0_____1", [[0, 7]]],
["0______1", [[0, 8]]]],
FZF.new([]).sort_by_rank(matcher.match(list, '01', '', '')))
assert_equal(
[["01", [[0, 1], [1, 2]]],
["01_", [[0, 1], [1, 2]]],
["_01_", [[1, 2], [2, 3]]],
["0____1", [[0, 1], [5, 6]]],
["0_____1", [[0, 1], [6, 7]]],
["____0_1", [[4, 5], [6, 7]]],
["0______1", [[0, 1], [7, 8]]],
["___01___", [[3, 4], [4, 5]]]],
FZF.new([]).sort_by_rank(xmatcher.match(list, '0 1', '', '')))
assert_equal(
[["_01_", [[1, 3], [0, 4]]],
["0____1", [[0, 6], [1, 3]]],
["0_____1", [[0, 7], [1, 3]]],
["0______1", [[0, 8], [1, 3]]],
["___01___", [[3, 5], [0, 2]]],
["____0_1", [[4, 7], [0, 2]]]],
FZF.new([]).sort_by_rank(xmatcher.match(list, '01 __', '', '')))
end
if RUBY_PLATFORM =~ /darwin/
NFD = '한글'
def test_nfc
assert_equal 6, NFD.length
assert_equal ["한글", [[0, 1], [1, 2]]],
FZF::UConv.nfc(NFD, [[0, 3], [3, 6]])
nfd2 = 'before' + NFD + 'after'
assert_equal 6 + 6 + 5, nfd2.length
nfc, offsets = FZF::UConv.nfc(nfd2, [[4, 14], [9, 13]])
o1, o2 = offsets
assert_equal 'before한글after', nfc
assert_equal 're한글af', nfc[(o1.first...o1.last)]
assert_equal '글a', nfc[(o2.first...o2.last)]
end
def test_nfd
nfc = '한글'
nfd = FZF::UConv.nfd(nfc)
assert_equal 6, nfd.length
assert_equal NFD, nfd
end
end
def test_split
assert_equal ["a", "b", "c", "\xFF", "d", "e", "f"],
FZF::UConv.split("abc\xFFdef")
end
end