Selecting files, fast
========================

.. only:: man

    Overview
    --------------

.. versionadded:: 0.45.0

.. only:: not man

    .. figure:: /screenshots/choose-files.webp
        :alt: The choose files kitten, showing metadata and title from an e-book file
        :align: center
        :width: 100%


The choose-files kitten is designed to allow you to select files, very fast,
with just a few key strokes. It operates like `fzf
<https://github.com/junegunn/fzf/>`__ and similar fuzzy finders, except that
it is specialised for finding files. As such it supports features such as
filtering by file type, file type icons, content previews and
so on, out of the box. It can be used as a drop in (but much more efficient and
keyboard friendly) replacement for the :guilabel:`File open and save`
dialog boxes common to GUI programs. On Linux, with the help of the
:doc:`desktop-ui </kittens/desktop-ui>` kitten, you can even convince
most GUI programs on your computer to use this kitten instead of regular file
dialogs.

Simply run it as::

    kitten choose-files

to select a single file from the tree rooted at the current working directory.

Type a few letters from the filename and once it becomes the top selection,
press :kbd:`Enter`. You can change the current directory by selecting a
directory and pressing the :kbd:`Tab` key. :kbd:`Shift+Tab` goes up one
directory level.

If you want to choose a file and insert it into your shell prompt at the
current cursor position, press :sc:`insert_chosen_file` for files or
:sc:`insert_chosen_directory` for directories. Similarly, to have a file
chosen in a command line, use, for example::

    some-command $(kitten choose-file)

Note that the above may not work in a complicated pipeline as it performs
terminal I/O and needs exclusive access to the tty device while choosing a
file.

.. note:: For content previews, this kitten uses some external programs. In
   particular `ffmpeg <https://www.ffmpeg.org/>`__ is needed for video
   previews and `calibre <https://calibre-ebook.com>`__ is needed
   for ebook metadata and cover preiews.

Creating shortcuts to favorite/frequently used directories
------------------------------------------------------------

You can create keyboard shortcuts to quickly switch to any directory in
:file:`choose-files.conf`. For example:

.. code-block:: conf

   map ctrl+t cd /tmp
   map alt+p  cd ~/my/project

Selecting multiple files
-----------------------------

When you wish to select multiple files, start the kitten with :option:`--mode
<kitty +kitten choose_files --mode>`:code:`=files`. Then instead of pressing
:kbd:`Enter`, press :kbd:`Shift+Enter` instead and the file will be added to the list
of selections. You can also hold the :kbd:`Ctrl` key and click on files to add
them to the selections. Similarly, you can hold the :kbd:`Alt` key and click to
select ranges of files (similar to using :kbd:`Shift+click` in a GUI app).
Press :kbd:`Enter` on the last selected file to finish. The list of selected
files is displayed at the bottom of the kitten and you can click on them
to deselect a file. Similarly, pressing :kbd:`Shift+Enter` will un-select a
previously selected file.


Hidden and ignored files
--------------------------

By default, the kitten does not process hidden files and directories (whose
names start with a period). This can be :opt:`changed in the configuration <kitten-choose_files.show_hidden>`
and also at runtime via the clickable link to the right of the search input.

Similarly, the kitten respects both :file:`.gitignore` and :file:`.ignore`
files, by default. This can also be changed both :opt:`in configuration
<kitten-choose_files.respect_ignores>` or at runtime. Note that
:file:`.gitignore` files are only respected if there is also a :file:`.git`
directory present. The kitten also supports the global :file:`.gitignore` file,
though it applies only inside git working trees. You can specify :opt:`global ignore
patterns <kitten-choose_files.ignore>`, that apply everywhere in :file:`choose-files.conf`.


Selecting non-existent files (save file names)
-------------------------------------------------

This kitten can also be used to select non-existent files, that is a new file
for a :guilabel:`Save file` type of dialog using :option:`--mode <kitty +kitten
choose_files --mode>`:code:`=save-file`. Once you have changed to the directory
you want the file to be in (using the :kbd:`Tab` key),
press :kbd:`Ctrl+Enter` and you will be able to type in the file name. If you
wish to modify an existing file name use :kbd:`Alt+Enter` to modify the
filename of the current top match instead.


Selecting directories
---------------------------

This kitten can also be used to select directories,
for an :guilabel:`Open directory` type of dialog using :option:`--mode <kitty +kitten
choose_files --mode>`:code:`=dir`. Once you have changed to the directory
you want, press :kbd:`Ctrl+Enter` to accept it. Or if you are in a parent
directory you can select a descendant directory by pressing :kbd:`Enter`, the
same as you would for selecting a file to open.


Selecting files or directories
--------------------------------

To select any existing path, whether it is a file or a directory, use
:option:`--mode <kitty +kitten choose_files --mode>`:code:`=all`. Press
:kbd:`Enter` to select the highlighted path. You can still use :kbd:`Tab` to
change into a highlighted directory and :kbd:`Ctrl+Enter` to select the
current directory itself.


Editing the search text
----------------------------

The search/filter text box uses the same line editing engine as the shell
prompt kitten, supporting the usual Emacs-style editing shortcuts such as
:kbd:`Ctrl+A`/:kbd:`Ctrl+E` to move to the start/end of the text,
:kbd:`Ctrl+Left`/:kbd:`Ctrl+Right` to move by a word, :kbd:`Ctrl+K`/:kbd:`Ctrl+U`
to delete to the end/start of the line, :kbd:`Ctrl+W`/:kbd:`Alt+D` to delete
the previous/next word and so on.

However, by default, the arrow keys as well as :kbd:`Home`, :kbd:`End`,
:kbd:`Ctrl+Home` and :kbd:`Ctrl+End` are bound to actions that navigate the
list of matched results, rather than moving the cursor within the search
text, since that is the more frequently needed behavior when quickly
filtering a list of files. If you prefer these keys to edit the search text
instead, as in a regular text input, you can rebind them to one of the
following actions in :file:`choose-files.conf`, which forward the key press
to the search text editor:

.. list-table::
    :widths: auto
    :header-rows: 1

    * - Action
      - Editing operation it performs
    * - :code:`edit_cursor_left`
      - Move the cursor one character to the left
    * - :code:`edit_cursor_right`
      - Move the cursor one character to the right
    * - :code:`edit_start_of_line`
      - Move the cursor to the start of the search text
    * - :code:`edit_end_of_line`
      - Move the cursor to the end of the search text
    * - :code:`edit_start_of_document`
      - Same as :code:`edit_start_of_line`, provided for symmetry with the shell prompt's line editor
    * - :code:`edit_end_of_document`
      - Same as :code:`edit_end_of_line`, provided for symmetry with the shell prompt's line editor
    * - :code:`edit_forward_word`
      - Move the cursor forward by one word
    * - :code:`edit_backward_word`
      - Move the cursor backward by one word
    * - :code:`edit_backspace`
      - Delete the character before the cursor
    * - :code:`edit_delete`
      - Delete the character after the cursor
    * - :code:`edit_kill_to_start_of_line`
      - Delete everything from the start of the line to the cursor
    * - :code:`edit_kill_to_end_of_line`
      - Delete everything from the cursor to the end of the line
    * - :code:`edit_kill_word_left`
      - Delete the word before the cursor
    * - :code:`edit_kill_word_right`
      - Delete the word after the cursor
    * - :code:`edit_yank`
      - Insert the most recently deleted text

For example, to make the arrow keys, :kbd:`Home` and :kbd:`End` edit the
search text instead of navigating the results list::

    map left    edit_cursor_left
    map right   edit_cursor_right
    map home    edit_start_of_line
    map end     edit_end_of_line
    map ctrl+home edit_start_of_document
    map ctrl+end  edit_end_of_document

Note that :kbd:`Up`, :kbd:`Down` and other keys not listed above continue to
be usable for navigating the results list even after applying the above
overrides. Also note that any key not bound to an action at all is
automatically forwarded to the search text editor, which is why keys such as
:kbd:`Backspace`, :kbd:`Delete`, :kbd:`Ctrl+K`, :kbd:`Ctrl+W` etc. already
edit the search text, without needing any of the above actions.


Configuration
------------------------

You can configure various aspects of the kitten's operation by creating a
:file:`choose-files.conf` in your :ref:`kitty config folder <confloc>`.
See below for the supported configuration directives.


.. include:: /generated/conf-kitten-choose_files.rst


.. include:: /generated/cli-kitten-choose_files.rst


