mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
BASH completion for ebook-convert
This commit is contained in:
parent
d6894a6789
commit
697bd3d12b
129
src/calibre/utils/complete.py
Normal file
129
src/calibre/utils/complete.py
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
from __future__ import with_statement
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
|
||||||
|
'''
|
||||||
|
BASH completion for calibre commands that are too complex for simple
|
||||||
|
completion.
|
||||||
|
'''
|
||||||
|
|
||||||
|
import sys, os, shlex, glob
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
from calibre import prints
|
||||||
|
|
||||||
|
debug = partial(prints, file=sys.stderr)
|
||||||
|
|
||||||
|
def split(src):
|
||||||
|
try:
|
||||||
|
return shlex.split(src)
|
||||||
|
except ValueError:
|
||||||
|
try:
|
||||||
|
return shlex.split(src+'"')
|
||||||
|
except ValueError:
|
||||||
|
return shlex.split(src+"'")
|
||||||
|
|
||||||
|
|
||||||
|
def files_and_dirs(prefix, allowed_exts=[]):
|
||||||
|
for i in glob.iglob(prefix+'*'):
|
||||||
|
_, ext = os.path.splitext(i)
|
||||||
|
ext = ext.lower().replace('.', '')
|
||||||
|
if os.path.isdir(i):
|
||||||
|
yield i+os.sep
|
||||||
|
elif allowed_exts is None or ext in allowed_exts:
|
||||||
|
yield i+' '
|
||||||
|
|
||||||
|
def get_opts_from_parser(parser, prefix):
|
||||||
|
def do_opt(opt):
|
||||||
|
for x in opt._long_opts:
|
||||||
|
if x.startswith(prefix):
|
||||||
|
yield x
|
||||||
|
for x in opt._short_opts:
|
||||||
|
if x.startswith(prefix):
|
||||||
|
yield x
|
||||||
|
for o in parser.option_list:
|
||||||
|
for x in do_opt(o): yield x
|
||||||
|
for g in parser.option_groups:
|
||||||
|
for o in g.option_list:
|
||||||
|
for x in do_opt(o): yield x
|
||||||
|
|
||||||
|
def send(ans):
|
||||||
|
for x in sorted(set(ans)):
|
||||||
|
x = x.replace(' ', '\\ ')
|
||||||
|
if x.endswith('\\ '):
|
||||||
|
x = x[:-2]+' '
|
||||||
|
prints(x)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class EbookConvert(object):
|
||||||
|
|
||||||
|
def __init__(self, comp_line, pos):
|
||||||
|
words = split(comp_line[:pos])
|
||||||
|
char_before = comp_line[pos-1]
|
||||||
|
prefix = words[-1] if words[-1].endswith(char_before) else ''
|
||||||
|
wc = len(words)
|
||||||
|
if not prefix:
|
||||||
|
wc += 1
|
||||||
|
self.words = words
|
||||||
|
self.prefix = prefix
|
||||||
|
self.previous = words[-2 if prefix else -1]
|
||||||
|
self.complete(wc)
|
||||||
|
|
||||||
|
def complete(self, wc):
|
||||||
|
if wc == 2:
|
||||||
|
self.complete_input()
|
||||||
|
elif wc == 3:
|
||||||
|
self.complete_output()
|
||||||
|
else:
|
||||||
|
from calibre.ebooks.conversion.cli import create_option_parser
|
||||||
|
from calibre.utils.logging import Log
|
||||||
|
log = Log()
|
||||||
|
log.outputs = []
|
||||||
|
ans = []
|
||||||
|
if not self.prefix or self.prefix.startswith('-'):
|
||||||
|
try:
|
||||||
|
parser, _ = create_option_parser(self.words[:3], log)
|
||||||
|
ans += list(get_opts_from_parser(parser, self.prefix))
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
if self.previous.startswith('-'):
|
||||||
|
ans += list(files_and_dirs(self.prefix, None))
|
||||||
|
send(ans)
|
||||||
|
|
||||||
|
def complete_input(self):
|
||||||
|
from calibre.ebooks.conversion.plumber import supported_input_formats
|
||||||
|
ans = list(files_and_dirs(self.prefix, supported_input_formats()))
|
||||||
|
from calibre.web.feeds.recipes import recipes
|
||||||
|
ans += [t.title+'.recipe ' for t in recipes if
|
||||||
|
(t.title+'.recipe').startswith(self.prefix)]
|
||||||
|
send(ans)
|
||||||
|
|
||||||
|
def complete_output(self):
|
||||||
|
from calibre.customize.ui import available_output_formats
|
||||||
|
fmts = available_output_formats()
|
||||||
|
ans = list(files_and_dirs(self.prefix, fmts))
|
||||||
|
ans += ['.'+x+' ' for x in fmts if ('.'+x).startswith(self.prefix)]
|
||||||
|
send(ans)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def main(args=sys.argv):
|
||||||
|
comp_line, pos = os.environ['COMP_LINE'], int(os.environ['COMP_POINT'])
|
||||||
|
module = split(comp_line)[0].split(os.sep)[-1]
|
||||||
|
if module == 'ebook-convert':
|
||||||
|
EbookConvert(comp_line, pos)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
raise sys.exit(main())
|
Loading…
x
Reference in New Issue
Block a user