file_chooser: add fuzzy subsequence search inline in .ins dialog

This commit is contained in:
slagernate 2026-05-07 16:02:36 -07:00
parent 03e9716936
commit 20c97bd500
1 changed files with 88 additions and 0 deletions

View File

@ -5839,6 +5839,77 @@ proc file_chooser_delete {} {
}
#### maxdepth: how many levels to descend for each $paths directory (-1: no limit)
proc fuzzy_chooser_inline {q} {
global file_chooser new_file_browser_depth new_file_browser_ext pathlist
if {$q eq {}} {
set file_chooser(files) {}
set file_chooser(fullpathlist) {}
set file_chooser(nitems) 0
.ins.center.leftdir.l selection clear 0 end
file_chooser_dirlist
return
}
set nfbe $new_file_browser_ext
if {[catch {regexp $nfbe {12345}}]} { set nfbe {} }
set allfiles [match_file {} {} $new_file_browser_depth 1]
set scored {}
foreach f $allfiles {
if {$nfbe ne {}} {
set ok 0
catch {set ok [regexp $nfbe $f]}
if {!$ok} continue
}
set sc [fuzzy_subseq_score $q $f]
if {$sc >= 0} { lappend scored [list $sc $f] }
}
set sorted [lsort -decreasing -integer -index 0 $scored]
set hits {}
set n 0
foreach pair $sorted {
if {$n >= 500} break
lappend hits [lindex $pair 1]
incr n
}
set seen_dir [dict create]
set new_dirs {}
foreach f $hits {
set d [file dirname $f]
if {![dict exists $seen_dir $d]} {
dict set seen_dir $d 1
lappend new_dirs $d
}
}
set new_tails {}
foreach d $new_dirs {
set t {}
foreach p $pathlist {
set pp [file dirname $p]/
if {[string first $pp $d] == 0} {
set t [string range $d [string length $pp] end]
break
}
}
if {$t eq {}} { set t [file tail $d] }
lappend new_tails $t
}
set file_chooser(dirs) $new_dirs
set file_chooser(dirtails) $new_tails
set file_chooser(files) $hits
set file_chooser(fullpathlist) $hits
set file_chooser(nitems) [llength $hits]
global dark_gui_colorscheme
if {$dark_gui_colorscheme} { set col cyan } else { set col blue }
set i 0
foreach p $file_chooser(dirs) {
if {[lsearch -exact $pathlist $p] != -1} {
.ins.center.leftdir.l itemconfigure $i -foreground $col -selectforeground $col
} else {
.ins.center.leftdir.l itemconfigure $i -foreground black -selectforeground black
}
incr i
}
}
proc file_chooser {} {
global file_chooser new_file_browser_ext new_file_browser_depth USER_CONF_DIR
set file_chooser(action) load
@ -5963,6 +6034,14 @@ proc file_chooser {} {
entry .ins.top3.ext_e -width 30 -takefocus 0 -state normal -textvariable new_file_browser_ext
balloon .ins.top3.ext_e "Show only files matching the\nextension regular expression"
label .ins.top3.fzf_l -text { Fuzzy:}
entry .ins.top3.fzf_e -width 25 -highlightcolor red -highlightthickness 2 \
-highlightbackground [option get . background {}]
balloon .ins.top3.fzf_e "Subsequence-match across all library paths.\nLeft pane shows dirs with hits; middle pane shows full paths."
bind .ins.top3.fzf_e <KeyRelease> {
fuzzy_chooser_inline [.ins.top3.fzf_e get]
}
button .ins.top4.select_current -takefocus 0 -text {Select current} -command {
set file_chooser(regex) {}
file_chooser_select [xschem get schname]
@ -6033,6 +6112,10 @@ proc file_chooser {} {
}
bind .ins.top3.pat_e <KeyRelease> {
if {[winfo exists .ins.top3.fzf_e] && [.ins.top3.fzf_e get] ne {}} {
.ins.top3.fzf_e delete 0 end
fuzzy_chooser_inline {}
}
file_chooser_search current
}
bind .ins.center.leftdir.l <<ListboxSelect>> {
@ -6135,6 +6218,8 @@ proc file_chooser {} {
pack .ins.top.editpaths -side left
pack .ins.top3.ext_l -side left
pack .ins.top3.ext_e -side left
pack .ins.top3.fzf_l -side left
pack .ins.top3.fzf_e -side left
if { [info exists file_chooser(geometry)]} {
wm geometry .ins "${file_chooser(geometry)}"
} elseif {[file exists $USER_CONF_DIR/file_chooser_geometry]} {
@ -6179,6 +6264,9 @@ proc file_chooser {} {
"set file_chooser(sp1) $file_chooser(sp1)\n" \
] $USER_CONF_DIR/file_chooser_geometry
}
set file_chooser(files) {}
set file_chooser(fullpathlist) {}
set file_chooser(nitems) 0
file_chooser_dirlist
file_chooser_filelist
set file_chooser(old_dirs) $file_chooser(dirs)