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
)
if '--uninstall' in ' '.join(sys.argv[1:]):
sys.exit(0)
try:
import PyQt4
except ImportError:
@ -324,6 +327,150 @@ else:
print "WARNING: The GUI needs PyQt >= 4.1.1"
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):
from subprocess import check_call
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.
"""
__version__ = "0.3.26"
__version__ = "0.3.27"
__docformat__ = "epytext"
__author__ = "Kovid Goyal <kovid@kovidgoyal.net>"

View File

@ -61,6 +61,17 @@ class FileFormatter(object):
return mode
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
def name_in_color():
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
for file in files:
file = FileFormatter(file, term)
name = file.name
name = file.name if ll else file.isdir_name
lsoutput.append(name)
if color: name = file.name_in_color
lscoloutput.append(name)

View File

@ -44,7 +44,7 @@ class ConversionError(Exception):
def option_parser(usage):
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.add_option('--header', action='store_true', default=False, dest='header',
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
from htmlentitydefs import name2codepoint
from urllib import urlopen, unquote
from urllib import unquote
from urlparse import urlparse
from tempfile import mkdtemp
from operator import itemgetter
@ -1121,12 +1121,12 @@ def parse_options(argv=None, cli=True):
raise ConversionError, 'no filename specified'
if options.title == None:
options.title = filename_to_utf8(os.path.splitext(os.path.basename(args[0]))[0])
return options, args
return options, args, parser
def main():
try:
options, args = parse_options()
options, args, parser = parse_options()
src = args[0]
except:
sys.exit(1)

View File

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

View File

@ -21,33 +21,39 @@ from libprs500.lrf import ConversionError, option_parser
from libprs500.lrf import Book
from libprs500.lrf.pylrs.pylrs import Paragraph, Italic, Bold, BookSetting
from libprs500 import filename_to_utf8
from libprs500 import iswindows
def main():
def parse_options(argv=None, cli=True):
""" CLI for txt -> lrf conversions """
parser = option_parser(\
if not argv:
argv = sys.argv[1:]
parser = option_parser(
"""usage: %prog [options] mybook.txt
%prog converts mybook.txt to mybook.lrf
"""\
"""
)
defenc = 'cp1252'
defenc = 'cp1252' if iswindows else 'utf8'
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', \
dest='encoding', help=enchelp, default=defenc)
options, args = parser.parse_args()
if len(args) != 1:
parser.print_help()
sys.exit(1)
src = os.path.abspath(os.path.expanduser(args[0]))
if cli:
parser.print_help()
raise ConversionError, 'no filename specified'
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:
convert_txt(src, options)
except ConversionError, err:
print >>sys.stderr, err
sys.exit(1)
options, args, parser = parse_options()
src = os.path.abspath(os.path.expanduser(args[0]))
except:
sys.exit(1)
convert_txt(src, options)
def convert_txt(path, options):