diff --git a/docs/kittens/choose-files.rst b/docs/kittens/choose-files.rst new file mode 100644 index 000000000..eaef88580 --- /dev/null +++ b/docs/kittens/choose-files.rst @@ -0,0 +1,23 @@ +Selecting files, fast +======================== + +.. only:: man + + Overview + -------------- + + +Configuration +------------------------ + +You can configure various aspects of the kitten's operation by creating a +:file:`choose-files.conf` in your :ref:`kitty config folder `. +See below for the supported configuration directives. + + +.. include:: /generated/conf-kitten-choose_files.rst + + +.. include:: /generated/cli-kitten-choose_files.rst + + diff --git a/kittens/choose_files/main.go b/kittens/choose_files/main.go index 8edb5d54a..2eaf2fb05 100644 --- a/kittens/choose_files/main.go +++ b/kittens/choose_files/main.go @@ -3,8 +3,10 @@ package choose_files import ( "fmt" "os" + "strings" "github.com/kovidgoyal/kitty/tools/cli" + "github.com/kovidgoyal/kitty/tools/config" "github.com/kovidgoyal/kitty/tools/tty" "github.com/kovidgoyal/kitty/tools/tui/loop" "github.com/kovidgoyal/kitty/tools/utils" @@ -14,12 +16,13 @@ var _ = fmt.Print var debugprintln = tty.DebugPrintln type State struct { - base_dir string - current_dir string - select_dirs bool - multiselect bool - max_depth int - search_text string + base_dir string + current_dir string + select_dirs bool + multiselect bool + max_depth int + exclude_patterns *utils.Set[string] + search_text string } func (s State) BaseDir() string { return utils.IfElse(s.base_dir == "", default_cwd, s.base_dir) } @@ -28,6 +31,9 @@ func (s State) Multiselect() bool { return s.multiselect } func (s State) MaxDepth() int { return utils.IfElse(s.max_depth < 1, 4, s.max_depth) } func (s State) String() string { return utils.Repr(s) } func (s State) SearchText() string { return s.search_text } +func (s State) ExcludePatterns() *utils.Set[string] { + return utils.IfElse(s.exclude_patterns == nil, utils.NewSet[string](2), s.exclude_patterns) +} func (s State) CurrentDir() string { return utils.IfElse(s.current_dir == "", s.BaseDir(), s.current_dir) } @@ -57,6 +63,17 @@ func (h *Handler) draw_screen() (err error) { return } +func load_config(opts *Options) (ans *Config, err error) { + ans = NewConfig() + p := config.ConfigParser{LineHandler: ans.Parse} + err = p.LoadConfig("choose-files.conf", opts.Config, opts.Override) + if err != nil { + return nil, err + } + // ans.KeyboardShortcuts = config.ResolveShortcuts(ans.KeyboardShortcuts) + return ans, nil +} + func (h *Handler) init_sizes(new_size loop.ScreenSize) { h.screen_size.width = int(new_size.WidthCells) h.screen_size.height = int(new_size.HeightCells) @@ -93,14 +110,34 @@ func (h *Handler) OnText(text string, from_key_event, in_bracketed_paste bool) ( return h.draw_screen() } +func (h *Handler) set_state_from_config(conf *Config) (err error) { + h.state.max_depth = int(conf.Max_depth) + h.state.exclude_patterns = utils.NewSet[string](len(conf.Exclude_directory)) + for _, x := range conf.Exclude_directory { + if strings.HasPrefix(x, "!") { + h.state.exclude_patterns.Discard(x[1:]) + } else { + h.state.exclude_patterns.Add(x) + } + } + return +} + var default_cwd string func main(_ *cli.Command, opts *Options, args []string) (rc int, err error) { + conf, err := load_config(opts) + if err != nil { + return 1, err + } lp, err := loop.New() if err != nil { return 1, err } handler := Handler{lp: lp} + if err = handler.set_state_from_config(conf); err != nil { + return 1, err + } switch len(args) { case 0: os.Getwd() diff --git a/kittens/choose_files/main.py b/kittens/choose_files/main.py index 09a615234..c2ab37079 100644 --- a/kittens/choose_files/main.py +++ b/kittens/choose_files/main.py @@ -3,8 +3,34 @@ import sys -from kitty.simple_cli_definitions import CompletionSpec +from kitty.conf.types import Definition +from kitty.constants import appname +from kitty.simple_cli_definitions import CONFIG_HELP, CompletionSpec +definition = Definition( + '!kittens.choose_files', +) + +agr = definition.add_group +egr = definition.end_group +opt = definition.add_option +map = definition.add_map +mma = definition.add_mouse_map + +agr('scan', 'Scanning the filesystem') +opt('+exclude_directory', '/proc', add_to_default=True, long_text=''' +Pattern to exclude directories. Can be specified multiple times. Matches against the absolute path to the directory. +If the pattern starts with :code:`!`, the :code:`!` is removed and the remaning pattern is removed from the list of patterns. This +can be used to remove the default excluded directory patterns. +''') +opt('+exclude_directory', '/dev', add_to_default=True) +opt('+exclude_directory', '/sys', add_to_default=True) + +opt('max_depth', '4', option_type='positive_int', long_text=''' +The maximum depth to which to scan the filesystem for matches. Using large values will slow things down considerably. The better +approach is to use a small value and first change to the directory of interest then actually select the file of interest. +''') +egr() def main(args: list[str]) -> None: raise SystemExit('This must be run as kitten choose-files') @@ -14,7 +40,19 @@ usage = '[directory to start choosing files in]' OPTIONS = ''' -'''.format +--override -o +type=list +Override individual configuration options, can be specified multiple times. +Syntax: :italic:`name=value`. For example: :option:`kitten choose_files -o` max_depth=20 + + +--config +type=list +completion=type:file ext:conf group:"Config files" kwds:none,NONE +{config_help} + + +'''.format(config_help=CONFIG_HELP.format(conf_name='diff', appname=appname)).format help_text = '''\ @@ -30,3 +68,5 @@ elif __name__ == '__doc__': cd['help_text'] = help_text cd['short_desc'] = 'Choose files, fast' cd['args_completion'] = CompletionSpec.from_string('type:directory') +elif __name__ == '__conf__': + sys.options_definition = definition # type: ignore