diff --git a/beetsplug/fish.py b/beetsplug/fish.py index 3a7682c2a..b81b9c387 100644 --- a/beetsplug/fish.py +++ b/beetsplug/fish.py @@ -1,5 +1,6 @@ # This file is part of beets. # Copyright 2015, winters jean-marie. +# Copyright 2020, Justin Mayer # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -12,12 +13,13 @@ # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. -"""If you use the fish-shell http://fishshell.com/ ... this will do -autocomplete for you. It does the main commands and options for beet -and the plugins. -It gives you all the album and itemfields (like genre, album) but not all the -values for these. It suggest genre: or album: but not genre: Pop..Jazz...Rock -You can get that by specifying ex. --extravalues genre. +"""This plugin generates tab completions for Beets commands for the Fish shell +, including completions for Beets commands, plugin +commands, and option flags. Also generated are completions for all the album +and track fields, suggesting for example `genre:` or `album:` when querying the +Beets database. Completions for the *values* of those fields are not generated by +default but can be included via the `-e` or `--extravalues` flag. For example: +`beet fish -e genre -e albumartist` """ from __future__ import (division, absolute_import, print_function, @@ -68,11 +70,11 @@ end class FishPlugin(BeetsPlugin): def commands(self): - cmd = ui.Subcommand('fish', help='make fish autocomplete beet') + cmd = ui.Subcommand('fish', help='generate Fish shell tab completions') cmd.func = self.run cmd.parser.add_option('-f', '--noFields', action='store_true', default=False, - help='no item/album fields for autocomplete') + help='omit album/track field completions') cmd.parser.add_option( '-e', '--extravalues', @@ -80,15 +82,15 @@ class FishPlugin(BeetsPlugin): type='choice', choices=library.Item.all_keys() + library.Album.all_keys(), - help='pick field, get field-values for autocomplete') + help='include specified field *values* in completions') return [cmd] def run(self, lib, opts, args): - # we gather the commands from beet and from the plugins. - # we take the album and item fields. - # it wanted, we take the values from these fields. - # we make a giant string of tehm formatted in a way that - # allows fish to do autocompletion for beet. + # Gather the commands from Beets core and its plugins. + # Collect the album and track fields. + # If specified, also collect the values for these fields. + # Make a giant string of all the above, formatted in a way that + # allows Fish to do tab completion for the `beet` command. homeDir = os.path.expanduser("~") completePath = os.path.join(homeDir, '.config/fish/completions') try: @@ -97,22 +99,22 @@ class FishPlugin(BeetsPlugin): if not os.path.isdir(completePath): raise pathAndFile = os.path.join(completePath, 'beet.fish') - nobasicfields = opts.noFields # do not complete for item/album fields - extravalues = opts.extravalues # ex complete all artist values + nobasicfields = opts.noFields # Do not complete for album/track fields + extravalues = opts.extravalues # e.g., Also complete artists names beetcmds = sorted( (commands.default_commands + commands.plugins.commands()), key=attrgetter('name')) fields = sorted(set( library.Album.all_keys() + library.Item.all_keys())) - # collect cmds and their aliases and their help message + # Collect commands, their aliases, and their help text cmd_names_help = [] for cmd in beetcmds: names = ["\?" if alias == "?" else alias for alias in cmd.aliases] names.append(cmd.name) for name in names: cmd_names_help.append((name, cmd.help)) - # here we go assembling the string + # Concatenate the string totstring = HEAD + "\n" totstring += get_cmds_list([name[0] for name in cmd_names_help]) totstring += '' if nobasicfields else get_standard_fields(fields) @@ -124,7 +126,7 @@ class FishPlugin(BeetsPlugin): "setup field completion for subcommands") + "\n" totstring += get_subcommands( cmd_names_help, nobasicfields, extravalues) - # setup completion for all the command-options + # Set up completion for all the command options totstring += get_all_commands(beetcmds) with open(pathAndFile, 'w') as fish_file: @@ -132,7 +134,7 @@ class FishPlugin(BeetsPlugin): def get_cmds_list(cmds_names): - # make list of all commands in beet&plugins + # Make a list of all Beets core & plugin commands substr = '' substr += ( "set CMDS " + " ".join(cmds_names) + ("\n" * 2) @@ -141,7 +143,7 @@ def get_cmds_list(cmds_names): def get_standard_fields(fields): - # make list of item/album fields & append with ':' + # Make a list of album/track fields and append with ':' fields = (field + ":" for field in fields) substr = '' substr += ( @@ -151,8 +153,8 @@ def get_standard_fields(fields): def get_extravalues(lib, extravalues): - # make list of all values from a item/album field - # so type artist: and get completion for stones, beatles .. + # Make a list of all values from an album/track field. + # 'beet ls albumartist: ' yields completions for ABBA, Beatles, etc. word = '' setOfValues = get_set_of_values_for_field(lib, extravalues) for fld in extravalues: @@ -165,7 +167,7 @@ def get_extravalues(lib, extravalues): def get_set_of_values_for_field(lib, fields): - # get the unique values from a item/album field + # Get unique values from a specified album/track field dictOfFields = {} for each in fields: dictOfFields[each] = set() @@ -196,7 +198,7 @@ def get_basic_beet_options(): def get_subcommands(cmd_name_and_help, nobasicfields, extravalues): - # formatting for fish to complete our fields/values + # Formatting for Fish to complete our fields/values word = "" for cmdname, cmdhelp in cmd_name_and_help: word += "\n" + "# ------ {} -------".format( @@ -224,7 +226,7 @@ def get_subcommands(cmd_name_and_help, nobasicfields, extravalues): def get_all_commands(beetcmds): - # formatting for fish to complete command-options + # Formatting for Fish to complete command options word = "" for cmd in beetcmds: names = ["\?" if alias == "?" else alias for alias in cmd.aliases] @@ -259,12 +261,12 @@ def get_all_commands(beetcmds): def clean_whitespace(word): - # remove to much whitespace,tabs in string + # Remove excess whitespace and tabs in a string return " ".join(word.split()) def wrap(word): - # need " or ' around strings but watch out if they're in the string + # Need " or ' around strings but watch out if they're in the string sptoken = '\"' if ('"') in word and ("'") in word: word.replace('"', sptoken) diff --git a/docs/plugins/fish.rst b/docs/plugins/fish.rst index a6e41a46d..b2cb096ee 100644 --- a/docs/plugins/fish.rst +++ b/docs/plugins/fish.rst @@ -1,43 +1,52 @@ -Fish plugins -============ - -The ``fish`` plugin adds a ``beet fish`` command that will create a fish -autocompletion file ``beet.fish`` in ``~/.config/fish/completions`` -This makes `fish`_ - a different shell - autocomplete commands for beet. - -.. _fish: http://fishshell.com/ - -Configuring +Fish Plugin =========== -This will only make sense if you have the `fish`_ shell installed. -Enable the ``fish`` plugin (see :ref:`using-plugins`). -If you install or disable plugins, run ``beet fish`` again. It takes the values -from the plugins you have enabled. +The ``fish`` plugin adds a ``beet fish`` command that creates a `Fish shell`_ +tab-completion file named ``beet.fish`` in ``~/.config/fish/completions``. +This enables tab-completion of ``beet`` commands for the `Fish shell`_. -Using -===== +.. _Fish shell: https://fishshell.com/ -Type ``beet fish``. Hit ``enter`` and will see the file ``beet.fish`` appear -in ``.config/fish/completions`` in your home folder. +Configuration +------------- -For a not-fish user: After you type ``beet`` in your fish-prompt and ``TAB`` -you will get the autosuggestions for all your plugins/commands and -typing ``-`` will get you all the options available to you. -If you type ``beet ls`` and you ``TAB`` you will get a list of all the album/item -fields that beet offers. Start typing ``genr`` ``TAB`` and fish completes -``genre:`` ... ready to type on... +Enable the ``fish`` plugin (see :ref:`using-plugins`) on a system running the +`Fish shell`_. + +Usage +----- + +Type ``beet fish`` to generate the ``beet.fish`` completions file at: +``~/.config/fish/completions/``. If you later install or disable plugins, run +``beet fish`` again to update the completions based on the enabled plugins. + +For users not accustomed to tab completion… After you type ``beet`` followed by +a space in your shell prompt and then the ``TAB`` key, you should see a list of +the beets commands (and their abbreviated versions) that can be invoked in your +current environment. Similarly, typing ``beet -`` will show you all the +option flags available to you, which also applies to subcommands such as +``beet import -``. If you type ``beet ls`` followed by a space and then the +and the ``TAB`` key, you will see a list of all the album/track fields that can +be used in beets queries. For example, typing ``beet ls ge`` will complete +to ``genre:`` and leave you ready to type the rest of your query. Options -======= +------- -The default is that you get autocompletion for all the album/item fields. -You can disable that with ``beet fish -f`` In that case you only get all -the plugins/commands/options. Everything else you type in yourself. -If you want completion for a specific album/item field, you can get that like -this ``beet fish -e genre`` or ``beet fish -e genre -e albumartist`` . -Then when you type at your fish-prompt ``beet list genre:`` and you ``TAB`` -you will get a list of all your genres to choose from. -REMEMBER : we get all the values of these fields and put them in the completion -file. It is not meant to be a replacement of your database. In other words : -speed and size matters. +In addition to beets commands, plugin commands, and option flags, the generated +completions also include by default all the album/track fields. If you only want +the former and do not want the album/track fields included in the generated +completions, use ``beet fish -f`` to only generate completions for beets/plugin +commands and option flags. + +If you want generated completions to also contain album/track field *values* for +the items in your library, you can use the ``-e`` or ``--extravalues`` option. +For example: ``beet fish -e genre`` or ``beet fish -e genre -e albumartist`` +In the latter case, subsequently typing ``beet list genre: `` will display +a list of all the genres in your library and ``beet list albumartist: `` +will show a list of the album artists in your library. Keep in mind that all of +these values will be put into the generated completions file, so use this option +with care when specified fields contain a large number of values. Libraries with, +for example, very large numbers of genres/artists may result in higher memory +utilization, completion latency, et cetera. This option is not meant to replace +database queries altogether.