Slide 1

Slide 1 text

BU(P$POGFSFODF4QSJOH Fuzzy finder as a
 Go library

Slide 2

Slide 2 text

XIPBNJ w LUS Ωλϩʔɺ!LUS@ w ৽ଔ w (Pͱ$-*πʔϧ͕͖͢

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

'V[[ZpOEFSJTԿ

Slide 5

Slide 5 text

wೖྗʹର͠ɺ͍͋·͍ݕࡧ
 ʹΑͬͯΠϯλϥΫςΟϒʹ
 ಛఆͷߦΛબ୒Ͱ͖Δ wίϚϯυϥΠϯGV[[ZpOEFS
 G[G G[Z FUD 'V[[ZpOEFS

Slide 6

Slide 6 text

$ cd `ghq root`/`ghq list | fzf` HIR഑ԼͷϦϙδτϦʹҠಈ

Slide 7

Slide 7 text

$ git branch | egrep -v '^\*' | fzf | 
 xargs git checkout ΠϯλϥΫςΟϒʹνΣοΫΞ΢τઌ
 ϒϥϯνΛબ୒

Slide 8

Slide 8 text

ίϚϯυϥΠϯGV[[ZpOEFSΛ
 ѻ͏ࡍʹൃੜ͢Δ໰୊

Slide 9

Slide 9 text

w ߦࢦ޲Ͱ͋ΔͨΊɺؚΊΒΕΔ৘ใྔʹ੍ݶ͕͋Δ w πʔϧʹ૊ΈࠐΉࡍͷෳࡶ͞ ίϚϯυϥΠϯGV[[ZpOEFS
 Λѻ͏ࡍʹൃੜ͢Δ໰୊

Slide 10

Slide 10 text

w ߦࢦ޲Ͱ͋ΔͨΊɺؚΊΒΕΔ৘ใྔʹ੍ݶ͕͋Δ w πʔϧʹ૊ΈࠐΉࡍͷෳࡶ͞ ίϚϯυϥΠϯGV[[ZpOEFS
 Λѻ͏ࡍʹൃੜ͢Δ໰୊

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

w શ͘ಉ͡಺༰Λද͍ࣔͯ͠Δߦ͕ෳ਺͋Δͱ͖ɺ
 ϓϩάϥϜతɺϢʔβతʹ΋ͦΕΒΛ۠ผͰ͖ͳ͍ w ৘ใྔΛ૿΍͢͜ͱͰϢχʔΫʹ͸Ͱ͖Δ͕ʜ w ͱʹ͔͘ݟͮΒ͍ w ิॿతͳ৘ใ΋ݕࡧର৅ʹͳΓɺݕࡧਫ਼౓͕௿Լ͢Δ ߦࢦ޲ͷݶք

Slide 15

Slide 15 text

w ߦࢦ޲Ͱ͋ΔͨΊɺؚΊΒΕΔ৘ใྔʹ੍ݶ͕͋Δ w πʔϧʹ૊ΈࠐΉࡍͷෳࡶ͞ ίϚϯυϥΠϯGV[[ZpOEFS
 Λѻ͏ࡍʹൃੜ͢Δ໰୊

Slide 16

Slide 16 text

w DEίϚϯυͷ֦ு w ύεͷཤྺΛΠϯλϥΫςΟϒʹબ୒ͯ͠Ҡಈ CCSFOIBODE

Slide 17

Slide 17 text

w J5VOFTΛίϚϯυϥΠϯ͔Βૢ࡞Ͱ͖Δ w J5VOFTͷۂΛΠϯλϥΫςΟϒʹબ୒ɺ࠶ੜ LUSJUVOFTDMJ

Slide 18

Slide 18 text

w ίϚϯυϥΠϯGV[[ZpOEFSͷΠϯετʔϧ w πʔϧʹೝࣝͤ͞ΔͨΊͷઃఆ w ؀ڥม਺ͳͲ πʔϧʹ૊ΈࠐΉࡍͷෳࡶ͞

Slide 19

Slide 19 text

'V[[ZpOEFSΛϥΠϒϥϦ
 ͱͯ͠ఏڙ͢Δ

Slide 20

Slide 20 text

w ߦࢦ޲Ͱ͋ΔͨΊɺؚΊΒΕΔ৘ใྔʹ੍ݶ͕͋Δ ‣ ಺෦తʹঢ়ଶΛ࣋ͭ͜ͱ͕Ͱ͖ɺϓϩάϥϜଆͰॏෳߦ Λ۠ผͰ͖Δ w πʔϧʹ૊ΈࠐΉࡍͷෳࡶ͞ ‣ (PʹͷΈґଘ͢ΔͨΊɺͦ΋ͦ΋πʔϧͷઃఆ͕ෆཁ 'V[[ZpOEFSBTBMJCSBSZ

Slide 21

Slide 21 text

LUSHPGV[[ZpOEFS

Slide 22

Slide 22 text

func Find( slice interface{}, itemFunc func(i int) string, opts ...Option, ) (idx int, err error) LUSHPGV[[ZpOEFS

Slide 23

Slide 23 text

EFNP

Slide 24

Slide 24 text

EFNP ίϚϯυϥΠϯGV[[ZpOEFS

Slide 25

Slide 25 text

func main() { var slice []string s := bufio.NewScanner(os.Stdin) for s.Scan() { slice = append(slice, s.Text()) } idx, err := fuzzyfinder.Find(slice, func(i int) string { return slice[i] }) if err != nil { fmt.Fprintf(os.Stderr, "failed to find: %s\n", err) os.Exit(1) } fmt.Println(slice[idx]) }

Slide 26

Slide 26 text

$ (cd $GOPATH/src/github.com/golang/go; git ls-files) | ./cli

Slide 27

Slide 27 text

EFNP ಉҰ಺༰ͷߦͷදࣔ

Slide 28

Slide 28 text

w ϓϩάϥϜࣗ਎͸ॏෳߦͷ൑ผ͕Ͱ͖Δ͕ɺ
 Ϣʔβ͸౰વ൑ผͰ͖ͳ͍ w ิॿతͳ৘ใΛϓϨϏϡʔ΢Πϯυ΢Ͱදࣔ ಉҰ಺༰ͷߦͷදࣔ

Slide 29

Slide 29 text

func main() { idx, err := fuzzyfinder.FindMulti(songs, func(i int) string { return songs[i].Title }, fuzzyfinder.WithPreviewWindow(func(i, w, h int) string { if i == -1 { return "" } return fmt.Sprintf( "Title: %s\nArtist: %s\nAlbum: %s\n", songs[i].Title, songs[i].ArtistName, songs[i].AlbumName) })) if err != nil { fmt.Fprintf(os.Stderr, "failed to find: %s\n", err) os.Exit(1) } for _, i := range idx { fmt.Println(fmt.Sprintf( "%s / %s / %s", songs[i].Title, songs[i].ArtistName, songs[i].AlbumName)) } }

Slide 30

Slide 30 text

$ ./orange

Slide 31

Slide 31 text

HPGV[[ZpOEFSͷ࣮૷

Slide 32

Slide 32 text

w ೖྗͱީิߦͷϚονϯά w Ϛονͨ͠ߦͷείΞϦϯά 'V[[ZpOEFSΛߏ੒͢Δཁૉ

Slide 33

Slide 33 text

w ೖྗlHSQDzΛؚΉߦΛ୳͢ w ۪௚ʹೋॏϧʔϓճ͚ͩ͢ Ϛονϯά

Slide 34

Slide 34 text

w ظ଴͍ͯ͠ΔߦΛ༏ઌతʹදࣔ͢ΔͨΊʹඞཁ w ֤ߦΛιʔτ͢ΔͨΊͷείΞΛࢉग़͢Δ είΞϦϯά

Slide 35

Slide 35 text

w ϨʔϕϯγϡλΠϯڑ཭ w /FFEMFNBO8VOTDI w 4NJUI8BUFSNBO ৭ʑͳείΞϦϯάΞϧΰϦζϜ

Slide 36

Slide 36 text

w ϨʔϕϯγϡλΠϯڑ཭εϖϧνΣοΧʔ w /FFEMFNBO8VOTDIG[Z w 4NJUI8BUFSNBOG[G ৭ʑͳείΞϦϯάΞϧΰϦζϜ

Slide 37

Slide 37 text

w ϨʔϕϯγϡλΠϯڑ཭ w /FFEMFNBO8VOTDI w 4NJUI8BUFSNBO ৭ʑͳείΞϦϯάΞϧΰϦζϜ

Slide 38

Slide 38 text

w άϩʔόϧ ΞϥΠϯϝϯτΞϧΰϦζϜͷҰͭ w ͋ΔͭͷจࣈྻΛ੔ྻͤ͞ΔͨΊʹ
 ඞཁͳίετΛಈతܭը๏Λ࢖ͬͯٻΊΔ /FFEMFNBO8VOTDIΞϧΰϦζϜ

Slide 39

Slide 39 text

/FFEMFNBO8VOTDIΞϧΰϦζϜ | A T A C ------------------------- | A| C|

Slide 40

Slide 40 text

w ҎԼͷ͍ͣΕ͔ͷૢ࡞ͷ͏ͪɺ࠷΋είΞ͕ߴ͍΋ͷΛબ୒ w ۭന Ϊϟοϓ ΛࠨͷจࣈྻʹҰͭૠೖ w ۭന Ϊϟοϓ Λ্ͷจࣈྻʹҰͭૠೖ w จࣈͱจࣈͷରԠ෇͚ ϚονPSϛεϚον /FFEMFNBO8VOTDIΞϧΰϦζϜ

Slide 41

Slide 41 text

w ҎԼͷ͍ͣΕ͔ͷૢ࡞ͷ͏ͪɺ࠷΋είΞ͕ߴ͍΋ͷΛબ୒ w ۭന Ϊϟοϓ ΛࠨͷจࣈྻʹҰͭૠೖ w ۭന Ϊϟοϓ Λ্ͷจࣈྻʹҰͭૠೖ w จࣈͱจࣈͷରԠ෇͚ ϚονPSϛεϚον PS /FFEMFNBO8VOTDIΞϧΰϦζϜ

Slide 42

Slide 42 text

/FFEMFNBO8VOTDIΞϧΰϦζϜ ยํ͕ۭจࣈͷͱ͖ͷ
 είΞ͸࠷ॳʹٻ·Δ | A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 C| -4

Slide 43

Slide 43 text

/FFEMFNBO8VOTDIΞϧΰϦζϜ e.g.
 
 “ATAC” ʹରͯ͠ “” ΛΞϥ Πϯϝϯτ͢Δʹ͸ 4 ͭ ΪϟοϓΛૠೖ͢Ε͹ྑ͍ | A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 C| -4

Slide 44

Slide 44 text

/FFEMFNBO8VOTDIΞϧΰϦζϜ “” ͱ “” ʹͦΕͧΕ จࣈΛରԠ෇͚Δ৔߹ɺ Ϛον͍ͯ͠ΔͷͰ +2
 (0 + 2 = 2) | A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 C| -4

Slide 45

Slide 45 text

/FFEMFNBO8VOTDIΞϧΰϦζϜ “A” ͱ “” ͕͋Γɺ
 ޙऀʹΪϟοϓΛૠೖ
 ͢ΔͷͰ -2 (-2 - 2 = -4) | A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 C| -4

Slide 46

Slide 46 text

/FFEMFNBO8VOTDIΞϧΰϦζϜ “” ͱ “A” ͕͋Γɺ
 લऀʹΪϟοϓΛૠೖ
 ͢ΔͷͰ -2
 (-2 - 2 = -4) | A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 C| -4

Slide 47

Slide 47 text

/FFEMFNBO8VOTDIΞϧΰϦζϜ match = 2 left gap = -4 top gap = -4
 
 Ͳ͔͜ΒٻΊ͔ͨΛه࿥ | A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 2 C| -4

Slide 48

Slide 48 text

/FFEMFNBO8VOTDIΞϧΰϦζϜ mismatch = -3 left gap = 0 top gap = -6 | A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 2 0 C| -4

Slide 49

Slide 49 text

/FFEMFNBO8VOTDIΞϧΰϦζϜ match = -2 left gap = -2 top gap = -8 | A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 2 0 -2 C| -4

Slide 50

Slide 50 text

/FFEMFNBO8VOTDIΞϧΰϦζϜ mismatch = -7 left gap = -4 top gap = -10 | A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 2 0 -2 -4 C| -4

Slide 51

Slide 51 text

| A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 2 0 -2 -4 C| -4 0 1 -1 0 /FFEMFNBO8VOTDIΞϧΰϦζϜ ࠷ऴతͳঢ়ଶ

Slide 52

Slide 52 text

| A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 2 0 -2 -4 C| -4 0 1 -1 0 /FFEMFNBO8VOTDIΞϧΰϦζϜ ຤ඌͷείΞ͕
 ͜ͷจࣈྻؒͷείΞ 
 είΞ = 0

Slide 53

Slide 53 text

| A T A C ------------------------- | 0 -2 -4 -6 -8 A| -2 2 0 -2 -4 C| -4 0 1 -1 0 /FFEMFNBO8VOTDIΞϧΰϦζϜ A T A C | | A - - C ຤ඌ͔Β໼ҹͷॱʹḷΔ

Slide 54

Slide 54 text

w ϨʔϕϯγϡλΠϯڑ཭ w /FFEMFNBO8VOTDI w 4NJUI8BUFSNBO ৭ʑͳείΞϦϯάΞϧΰϦζϜ

Slide 55

Slide 55 text

w ϩʔΧϧΞϥΠϯϝϯτΞϧΰϦζϜͷҰͭ w શମతʹ͸ࣅ͍ͯͳ͍ͭͷจࣈྻͷ
 ہॴతͳΞϥΠϯϝϯτΛٻΊΔΞϧΰϦζϜ w /FFEMFNBO8VTDIͱඇৗʹࣅ͍ͯΔ͕ɺ
 είΞ͕ϚΠφεʹͳΒͳ͍ 4NJUI8BUFSNBOΞϧΰϦζϜ

Slide 56

Slide 56 text

4NJUI8BUFSNBOΞϧΰϦζϜ w ҎԼͷ͍ͣΕ͔ͷૢ࡞ͷ͏ͪɺ࠷΋είΞ͕ߴ͍΋ͷΛબ୒ w ۭന Ϊϟοϓ ΛࠨͷจࣈྻʹҰͭૠೖ w ۭന Ϊϟοϓ Λ্ͷจࣈྻʹҰͭૠೖ w จࣈͱจࣈͷରԠ෇͚ ϚονPSϛεϚον w θϩ஋

Slide 57

Slide 57 text

| A T A C ------------------------- | 0 0 0 0 0 A| 0 2 0 2 0 C| 0 0 1 0 4 4NJUI8BUFSNBOΞϧΰϦζϜ ຤ඌ͔Βઌ಄Ͱ͸ͳ͘ɺ ෦෼తͳΞϥΠϯϝϯτ (຤ඌ͔Β 0 ·Ͱ)

Slide 58

Slide 58 text

| A T A C ------------------------- | 0 0 0 0 0 A| 0 2 0 2 0 C| 0 0 1 0 4 4NJUI8BUFSNBOΞϧΰϦζϜ είΞ = 4

Slide 59

Slide 59 text

| A T A C ------------------------- | 0 0 0 0 0 A| 0 2 0 2 0 C| 0 0 1 0 4 4NJUI8BUFSNBOΞϧΰϦζϜ A T A C | | - - A C

Slide 60

Slide 60 text

w ΪϟοϓΛ࡞Δ͜ͱࣗମ΁ͷϖφϧςΟ w ઌ಄ҰகϘʔφε w FUD ϘʔφεͱϖφϧςΟ

Slide 61

Slide 61 text

w ઃܭ͸ͦΕͧΕͷ࣮૷ʹΑΔ w G[ZKIBXUIPSOG[Z"-(03*5).NE w G[GKVOFHVOOG[GTSDBMHPBMHPHP ϘʔφεͱϖφϧςΟ

Slide 62

Slide 62 text

·ͱΊ

Slide 63

Slide 63 text

ೖྗʹϚον͢ΔߦΛߜΓࠐΉ 4NJUI8BUFSNBOͰ֤ߦΛείΞϦϯά είΞ͕ߴ͍΋ͷ͔Βॱʹදࣔ HPGV[[ZpOEFSͷ࣮૷

Slide 64

Slide 64 text

w ॏෳߦͷ۠ผ w ϓϨϏϡʔ΢Πϯυ΢Ͱͷิॿతͳ৘ใͷ෇༩ w πʔϧ͔ΒGV[[ZpOEFSΛͭ͘Δࡍʹɺ
 ίϚϯυϥΠϯGV[[ZpOEFS΁ͷґଘΛղফͰ ͖Δ HPGV[[ZpOEFSͷղܾ͢Δ͜ͱ

Slide 65

Slide 65 text

5IBOLTGPSMJTUFOJOH