Adding limit and its documentation

This commit is contained in:
Patrick Nicholson 2021-12-07 18:47:55 -05:00
parent 736443708b
commit cdb6b21f1a
2 changed files with 147 additions and 0 deletions

95
beetsplug/limit.py Normal file
View file

@ -0,0 +1,95 @@
# This file is part of beets.
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
from beets.dbcore import FieldQuery
from beets.plugins import BeetsPlugin
from beets.ui import Subcommand, decargs, print_
from collections import deque
from itertools import islice
def lslimit(lib, opts, args):
"""Query command with head/tail"""
head = opts.head
tail = opts.tail
if head and tail:
raise RuntimeError("Only use one of --head and --tail")
query = decargs(args)
if opts.album:
objs = lib.albums(query)
else:
objs = lib.items(query)
if head:
objs = islice(objs, head)
elif tail:
objs = deque(objs, tail)
for obj in objs:
print_(format(obj))
lslimit_cmd = Subcommand(
"lslimit",
help="query with optional head or tail"
)
lslimit_cmd.parser.add_option(
'--head',
action='store',
type="int",
default=None
)
lslimit_cmd.parser.add_option(
'--tail',
action='store',
type="int",
default=None
)
lslimit_cmd.parser.add_all_common_options()
lslimit_cmd.func = lslimit
class LsLimitPlugin(BeetsPlugin):
def commands(self):
return [lslimit_cmd]
class HeadPlugin(BeetsPlugin):
"""Head of an arbitrary query.
This allows a user to limit the results of any query to the first
`pattern` rows. Example usage: return first 10 tracks `beet ls '<10'`.
"""
def queries(self):
class HeadQuery(FieldQuery):
"""Singleton query implementation that tracks result count."""
n = 0
include = True
@classmethod
def value_match(cls, pattern, value):
cls.n += 1
if cls.include:
cls.include = cls.n <= int(pattern)
return cls.include
return {
"<": HeadQuery
}

52
docs/plugins/limit.rst Normal file
View file

@ -0,0 +1,52 @@
Limit Query Plugin
==================
``limit`` is a plugin to limit a query to the first or last set of
results. We also provide a query prefix ``'<n'`` to inline the same
behavior in the ``list`` command. They are analagous to piping results:
$ beet [list|ls] [QUERY] | [head|tail] -n n
There are two provided interfaces:
1. ``beet lslimit [--head n | --tail n] [QUERY]`` returns the head or
tail of a query
2. ``beet [list|ls] [QUERY] '<n'`` returns the head of a query
There are two differences in behavior:
1. The query prefix does not support tail.
2. The query prefix could appear anywhere in the query but will only
have the same behavior as the ``lslimit`` command and piping to ``head``
when it appears last.
Performance for the query previx is much worse due to the current
singleton-based implementation.
So why does the query prefix exist? Because it composes with any other
query-based API or plugin (see :doc:`/reference/query`). For example,
you can use the query prefix in ``smartplaylists`` (see :doc:`/plugins/
smartplaylists`) to limit the number of tracks in a smart playlist for
applications like most played and recently added.
Configuration
=============
Enable the ``last`` plugin in your configuration (see
:ref:`using-plugins`).
Examples
========
First 10 tracks
$ beet ls | head -n 10
$ beet lslimit --head 10
$ beet ls '<10'
100 mostly recently released tracks
$ beet lslimit --tail 100 year+ month+ day+
$ beet ls year- month- day- '<100'