Added BASH completion to the CLI

prs500 ls now outputs a trailing slash on directory names
This commit is contained in:
Kovid Goyal 2007-05-13 04:10:22 +00:00
parent 46f537ed86
commit 81b81b4ae8
7 changed files with 198 additions and 25 deletions

147
setup.py
View File

@ -313,6 +313,9 @@ setup(
**py2exe_options **py2exe_options
) )
if '--uninstall' in ' '.join(sys.argv[1:]):
sys.exit(0)
try: try:
import PyQt4 import PyQt4
except ImportError: except ImportError:
@ -324,6 +327,150 @@ else:
print "WARNING: The GUI needs PyQt >= 4.1.1" print "WARNING: The GUI needs PyQt >= 4.1.1"
import os import os
def options(parse_options):
options, args, parser = parse_options(['dummy'], cli=False)
options = parser.option_list
for group in parser.option_groups:
options += group.option_list
opts = []
for opt in options:
opts.extend(opt._short_opts)
opts.extend(opt._long_opts)
return opts
def opts_and_exts(name, op, exts):
opts = ' '.join(options(op))
exts.extend([i.upper() for i in exts])
exts='|'.join(exts)
return '_'+name+'()'+\
'''
{
local cur prev opts
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
opts="%s"
pics="@(jpg|jpeg|png|gif|bmp|JPG|JPEG|PNG|GIF|BMP)"
case "${prev}" in
--cover )
_filedir "${pics}"
return 0
;;
esac
case "${cur}" in
--cover )
_filedir "${pics}"
return 0
;;
-* )
COMPREPLY=( $(compgen -W "${opts}" -- ${cur}) )
return 0
;;
* )
_filedir '@(%s)'
return 0
;;
esac
}
complete -o filenames -F _'''%(opts,exts) + name + ' ' + name +"\n\n"
if os.access('/etc/bash_completion.d', os.W_OK):
try:
print 'Setting up bash completion...',
sys.stdout.flush()
from libprs500.lrf.html.convert_from import parse_options as htmlop
from libprs500.lrf.txt.convert_from import parse_options as txtop
from libprs500.lrf.meta import parse_options as metaop
f = open('/etc/bash_completion.d/libprs500', 'wb')
f.write('# libprs500 Bash Shell Completion\n')
f.write(opts_and_exts('html2lrf', htmlop,
['htm', 'html', 'xhtml', 'xhtm', 'rar', 'zip']))
f.write(opts_and_exts('txt2lrf', txtop, ['txt']))
f.write(opts_and_exts('lrf-meta', metaop, ['lrf']))
f.write('''
_prs500_ls()
{
local pattern search listing prefix
pattern="$1"
search="$1"
if [[ -n "{$pattern}" ]]; then
if [[ "${pattern:(-1)}" == "/" ]]; then
pattern=""
else
pattern="$(basename ${pattern} 2> /dev/null)"
search="$(dirname ${search} 2> /dev/null)"
fi
fi
if [[ "x${search}" == "x" || "x${search}" == "x." ]]; then
search="/"
fi
listing="$(prs500 ls ${search} 2>/dev/null)"
prefix="${search}"
if [[ "x${prefix:(-1)}" != "x/" ]]; then
prefix="${prefix}/"
fi
echo $(compgen -P "${prefix}" -W "${listing}" "${pattern}")
}
_prs500()
{
local cur prev
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
COMPREPLY=()
case "${prev}" in
ls|rm|mkdir|touch|cat )
COMPREPLY=( $(_prs500_ls "${cur}") )
return 0
;;
cp )
if [[ ${cur} == prs500:* ]]; then
COMPREPLY=( $(_prs500_ls "${cur:7}") )
return 0
else
_filedir
return 0
fi
;;
prs500 )
COMPREPLY=( $(compgen -W "cp ls rm mkdir touch cat info books df" "${cur}") )
return 0
;;
* )
if [[ ${cur} == prs500:* ]]; then
COMPREPLY=( $(_prs500_ls "${cur:7}") )
return 0
else
if [[ ${prev} == prs500:* ]]; then
_filedir
return 0
else
COMPREPLY=( $(compgen -W "prs500:" "${cur}") )
return 0
fi
return 0
fi
;;
esac
}
complete -o nospace -F _prs500 prs500
''')
f.close()
print 'done'
except:
print 'failed'
if os.access('/etc/udev/rules.d', os.W_OK): if os.access('/etc/udev/rules.d', os.W_OK):
from subprocess import check_call from subprocess import check_call
print 'Trying to setup udev rules...', print 'Trying to setup udev rules...',

View File

@ -33,7 +33,7 @@ You may have to adjust the GROUP and the location of the rules file to
suit your distribution. suit your distribution.
""" """
__version__ = "0.3.26" __version__ = "0.3.27"
__docformat__ = "epytext" __docformat__ = "epytext"
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>" __author__ = "Kovid Goyal <kovid@kovidgoyal.net>"

View File

@ -61,6 +61,17 @@ class FileFormatter(object):
return mode return mode
return property(doc=doc, fget=fget) return property(doc=doc, fget=fget)
@apply
def isdir_name():
doc='''Return self.name + '/' if self is a directory'''
def fget(self):
name = self.name
if self.is_dir:
name += '/'
return name
return property(doc=doc, fget=fget)
@apply @apply
def name_in_color(): def name_in_color():
doc=""" The name in ANSI text. Directories are blue, ebooks are green """ doc=""" The name in ANSI text. Directories are blue, ebooks are green """
@ -140,7 +151,7 @@ def ls(dev, path, term, recurse=False, color=False, human_readable_size=False, l
if size > maxlen: maxlen = size if size > maxlen: maxlen = size
for file in files: for file in files:
file = FileFormatter(file, term) file = FileFormatter(file, term)
name = file.name name = file.name if ll else file.isdir_name
lsoutput.append(name) lsoutput.append(name)
if color: name = file.name_in_color if color: name = file.name_in_color
lscoloutput.append(name) lscoloutput.append(name)

View File

@ -44,7 +44,7 @@ class ConversionError(Exception):
def option_parser(usage): def option_parser(usage):
parser = OptionParser(usage=usage, version='libprs500 '+VERSION, parser = OptionParser(usage=usage, version='libprs500 '+VERSION,
epilog='html2lrf created by Kovid Goyal') epilog='Created by Kovid Goyal')
metadata = parser.add_option_group('METADATA OPTIONS') metadata = parser.add_option_group('METADATA OPTIONS')
metadata.add_option('--header', action='store_true', default=False, dest='header', metadata.add_option('--header', action='store_true', default=False, dest='header',
help='Add a header to all the pages with title and author.') help='Add a header to all the pages with title and author.')

View File

@ -22,7 +22,7 @@ and to Falstaff for pylrs.
""" """
import os, re, sys, shutil, traceback, copy import os, re, sys, shutil, traceback, copy
from htmlentitydefs import name2codepoint from htmlentitydefs import name2codepoint
from urllib import urlopen, unquote from urllib import unquote
from urlparse import urlparse from urlparse import urlparse
from tempfile import mkdtemp from tempfile import mkdtemp
from operator import itemgetter from operator import itemgetter
@ -1121,12 +1121,12 @@ def parse_options(argv=None, cli=True):
raise ConversionError, 'no filename specified' raise ConversionError, 'no filename specified'
if options.title == None: if options.title == None:
options.title = filename_to_utf8(os.path.splitext(os.path.basename(args[0]))[0]) options.title = filename_to_utf8(os.path.splitext(os.path.basename(args[0]))[0])
return options, args return options, args, parser
def main(): def main():
try: try:
options, args = parse_options() options, args, parser = parse_options()
src = args[0] src = args[0]
except: except:
sys.exit(1) sys.exit(1)

View File

@ -24,8 +24,7 @@ to get and set meta information. For example:
>>> lrf.category = "History" >>> lrf.category = "History"
""" """
import struct import struct, zlib, sys
import zlib
from shutil import copyfileobj from shutil import copyfileobj
from cStringIO import StringIO from cStringIO import StringIO
import xml.dom.minidom as dom import xml.dom.minidom as dom
@ -538,10 +537,11 @@ class LRFMetaFile(object):
self._file.write(val) self._file.write(val)
def main(): def parse_options(argv=None, cli=True):
import sys, os.path
from optparse import OptionParser from optparse import OptionParser
from libprs500 import __version__ as VERSION from libprs500 import __version__ as VERSION
if not argv:
argv = sys.argv[1:]
parser = OptionParser(usage = \ parser = OptionParser(usage = \
"""%prog [options] mybook.lrf """%prog [options] mybook.lrf
@ -574,7 +574,16 @@ def main():
dest="page", help="Don't know what this is for") dest="page", help="Don't know what this is for")
options, args = parser.parse_args() options, args = parser.parse_args()
if len(args) != 1: if len(args) != 1:
parser.print_help() if cli:
parser.print_help()
raise LRFException, 'no filename specified'
return options, args, parser
def main():
import os.path
try:
options, args, parser = parse_options()
except:
sys.exit(1) sys.exit(1)
lrf = LRFMetaFile(open(args[0], "r+b")) lrf = LRFMetaFile(open(args[0], "r+b"))
if options.title: if options.title:

View File

@ -21,33 +21,39 @@ from libprs500.lrf import ConversionError, option_parser
from libprs500.lrf import Book from libprs500.lrf import Book
from libprs500.lrf.pylrs.pylrs import Paragraph, Italic, Bold, BookSetting from libprs500.lrf.pylrs.pylrs import Paragraph, Italic, Bold, BookSetting
from libprs500 import filename_to_utf8 from libprs500 import filename_to_utf8
from libprs500 import iswindows
def main(): def parse_options(argv=None, cli=True):
""" CLI for txt -> lrf conversions """ """ CLI for txt -> lrf conversions """
parser = option_parser(\ if not argv:
argv = sys.argv[1:]
parser = option_parser(
"""usage: %prog [options] mybook.txt """usage: %prog [options] mybook.txt
%prog converts mybook.txt to mybook.lrf %prog converts mybook.txt to mybook.lrf
"""\ """
) )
defenc = 'cp1252' if iswindows else 'utf8'
defenc = 'cp1252'
enchelp = 'Set the encoding used to decode ' + \ enchelp = 'Set the encoding used to decode ' + \
'the text in mybook.txt. Default encoding is ' + defenc 'the text in mybook.txt. Default encoding is %default'
parser.add_option('-e', '--encoding', action='store', type='string', \ parser.add_option('-e', '--encoding', action='store', type='string', \
dest='encoding', help=enchelp, default=defenc) dest='encoding', help=enchelp, default=defenc)
options, args = parser.parse_args() options, args = parser.parse_args()
if len(args) != 1: if len(args) != 1:
parser.print_help() if cli:
sys.exit(1) parser.print_help()
src = os.path.abspath(os.path.expanduser(args[0])) raise ConversionError, 'no filename specified'
if options.title == None: if options.title == None:
options.title = filename_to_utf8(os.path.splitext(os.path.basename(src))[0]) options.title = filename_to_utf8(os.path.splitext(os.path.basename(args[0]))[0])
return options, args, parser
def main():
try: try:
convert_txt(src, options) options, args, parser = parse_options()
except ConversionError, err: src = os.path.abspath(os.path.expanduser(args[0]))
print >>sys.stderr, err except:
sys.exit(1) sys.exit(1)
convert_txt(src, options)
def convert_txt(path, options): def convert_txt(path, options):