 PRIVATE>
 
 : score ( full fuzzy -- n )
-    dup [
+    [
         [ [ length ] bi@ - 15 swap [-] 3 /f ] 2keep
         runs [
             [ 0 [ pick score-1 max ] reduce nip ] keep
             length * +
         ] with each
     ] [
-        2drop 0
-    ] if ;
+        drop 0
+    ] if* ;
 
 : rank-completions ( results -- newresults )
-    [ 0 [ first max ] reduce 4 /f ] keep
-    dup length 25 >
-    [ [ first-unsafe < ] with filter ] [ nip ] if
-    sort-keys <reversed> values ;
+    dup length 25 > [
+        [ [ first ] [ max ] map-reduce 4 /f ] keep
+        [ first < ] with filter
+    ] when sort-keys <reversed> values ;
 
 : complete ( full short -- score )
-    2dup [ <reversed> ] bi@ [ dupd fuzzy score ] 2bi@ max ;
+    [ dupd fuzzy score ] 2keep pick 0 > [
+        [ <reversed> ] bi@ dupd fuzzy score max
+    ] [ 2drop ] if ;
 
-: completion ( short candidate -- result )
-    [ second swap complete ] keep 2array ; inline
+: completion ( short candidate -- score result )
+    [ second swap complete ] keep ; inline
 
 : completion, ( short candidate -- )
-    completion dup first-unsafe 0 > [ , ] [ drop ] if ;
+    completion over 0 > [ 2array , ] [ 2drop ] if ;
 
 : completions ( short candidates -- seq )
     [ ] [

! Copyright (C) 2005, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
USING: accessors arrays assocs colors combinators
combinators.short-circuit fry io.directories io.files
io.files.info io.pathnames kernel locals make math math.order
sequences sequences.private sorting splitting
splitting.monotonic unicode unicode.data vectors vocabs
vocabs.hierarchy ;
IN: tools.completion

<PRIVATE

: smart-index-from ( obj i seq -- n/f )
    rot [ ch>lower ] [ ch>upper ] bi
    '[ dup _ eq? [ drop t ] [ _ eq? ] if ] find-from drop ;

:: (fuzzy) ( accum i full ch -- accum i ? )
    ch i full smart-index-from [
        [ accum push ]
        [ accum swap 1 + t ] bi
    ] [
        f -1 f
    ] if* ; inline

PRIVATE>

: fuzzy ( full short -- indices )
    dup [ length <vector> 0 ] curry 2dip
    [ (fuzzy) ] with all? 2drop ;

: runs ( seq -- newseq )
    [ 1 - = ] monotonic-split-slice ;

: score-1 ( i full -- n )
    {
        { [ over zero? ] [ 2drop 10 ] }
        { [ 2dup length 1 - = ] [ 2drop 4 ] }
        { [ 2dup [ 1 - ] dip nth-unsafe Letter? not ] [ 2drop 10 ] }
        { [ 2dup [ 1 + ] dip nth-unsafe Letter? not ] [ 2drop 4 ] }
        [ 2drop 1 ]
