mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Linux installer: Use pkg-config to get the location for installing the calibre bash completion scripts. pkg-config is used only when installing to /usr. Fixes #1340023 [bash-completion missing](https://bugs.launchpad.net/calibre/+bug/1340023)
This commit is contained in:
parent
e013415923
commit
a106f15d95
@ -4,11 +4,11 @@ __copyright__ = '2008, Kovid Goyal <kovid at kovidgoyal.net>'
|
|||||||
''' Post installation script for linux '''
|
''' Post installation script for linux '''
|
||||||
|
|
||||||
import sys, os, cPickle, textwrap, stat, errno
|
import sys, os, cPickle, textwrap, stat, errno
|
||||||
from subprocess import check_call
|
from subprocess import check_call, check_output
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from calibre import __appname__, prints, guess_type
|
from calibre import __appname__, prints, guess_type
|
||||||
from calibre.constants import islinux, isnetbsd, isbsd
|
from calibre.constants import islinux, isbsd
|
||||||
from calibre.customize.ui import all_input_formats
|
from calibre.customize.ui import all_input_formats
|
||||||
from calibre.ptempfile import TemporaryDirectory
|
from calibre.ptempfile import TemporaryDirectory
|
||||||
from calibre import CurrentDir
|
from calibre import CurrentDir
|
||||||
@ -162,6 +162,8 @@ if mimetype_icons and raw_input('Remove the ebook format icons? [y/n]:').lower()
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
# Completion {{{
|
||||||
|
|
||||||
class ZshCompleter(object): # {{{
|
class ZshCompleter(object): # {{{
|
||||||
|
|
||||||
def __init__(self, opts):
|
def __init__(self, opts):
|
||||||
@ -434,6 +436,154 @@ class ZshCompleter(object): # {{{
|
|||||||
f.write('esac\n')
|
f.write('esac\n')
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
def get_bash_completion_path(root, share, info):
|
||||||
|
if root == '/usr':
|
||||||
|
# Try to get the system bash completion dir since we are installing to
|
||||||
|
# /usr
|
||||||
|
try:
|
||||||
|
path = check_output('pkg-config --variable=completionsdir bash-completion'.split()).strip().partition(os.pathsep)[0]
|
||||||
|
except Exception:
|
||||||
|
info('Failed to find directory to install bash completions, skipping.')
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
if os.path.exists(path):
|
||||||
|
return os.path.join(path, 'calibre')
|
||||||
|
else:
|
||||||
|
# Use the default bash-completion dir under staging_share
|
||||||
|
return os.path.join(share, 'bash-completion', 'completions', 'calibre')
|
||||||
|
|
||||||
|
def write_completion(bash_comp_dest, zsh):
|
||||||
|
from calibre.ebooks.metadata.cli import option_parser as metaop, filetypes as meta_filetypes
|
||||||
|
from calibre.ebooks.lrf.lrfparser import option_parser as lrf2lrsop
|
||||||
|
from calibre.gui2.lrf_renderer.main import option_parser as lrfviewerop
|
||||||
|
from calibre.gui2.viewer.main import option_parser as viewer_op
|
||||||
|
from calibre.gui2.tweak_book.main import option_parser as tweak_op
|
||||||
|
from calibre.ebooks.metadata.sources.cli import option_parser as fem_op
|
||||||
|
from calibre.gui2.main import option_parser as guiop
|
||||||
|
from calibre.utils.smtp import option_parser as smtp_op
|
||||||
|
from calibre.library.server.main import option_parser as serv_op
|
||||||
|
from calibre.ebooks.oeb.polish.main import option_parser as polish_op, SUPPORTED
|
||||||
|
from calibre.ebooks.oeb.polish.import_book import IMPORTABLE
|
||||||
|
from calibre.debug import option_parser as debug_op
|
||||||
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
|
from calibre.customize.ui import available_input_formats
|
||||||
|
input_formats = sorted(all_input_formats())
|
||||||
|
tweak_formats = sorted(x.lower() for x in SUPPORTED|IMPORTABLE)
|
||||||
|
|
||||||
|
if bash_comp_dest and not os.path.exists(os.path.dirname(bash_comp_dest)):
|
||||||
|
os.makedirs(os.path.dirname(bash_comp_dest))
|
||||||
|
|
||||||
|
complete = 'calibre-complete'
|
||||||
|
if getattr(sys, 'frozen_path', None):
|
||||||
|
complete = os.path.join(getattr(sys, 'frozen_path'), complete)
|
||||||
|
|
||||||
|
with open(bash_comp_dest or os.devnull, 'wb') as f:
|
||||||
|
def o_and_e(*args, **kwargs):
|
||||||
|
f.write(opts_and_exts(*args, **kwargs))
|
||||||
|
zsh.opts_and_exts(*args, **kwargs)
|
||||||
|
def o_and_w(*args, **kwargs):
|
||||||
|
f.write(opts_and_words(*args, **kwargs))
|
||||||
|
zsh.opts_and_words(*args, **kwargs)
|
||||||
|
|
||||||
|
f.write('# calibre Bash Shell Completion\n')
|
||||||
|
o_and_e('calibre', guiop, BOOK_EXTENSIONS)
|
||||||
|
o_and_e('lrf2lrs', lrf2lrsop, ['lrf'], file_map={'--output':['lrs']})
|
||||||
|
o_and_e('ebook-meta', metaop,
|
||||||
|
list(meta_filetypes()), cover_opts=['--cover', '-c'],
|
||||||
|
opf_opts=['--to-opf', '--from-opf'])
|
||||||
|
o_and_e('ebook-polish', polish_op,
|
||||||
|
[x.lower() for x in SUPPORTED], cover_opts=['--cover', '-c'],
|
||||||
|
opf_opts=['--opf', '-o'])
|
||||||
|
o_and_e('lrfviewer', lrfviewerop, ['lrf'])
|
||||||
|
o_and_e('ebook-viewer', viewer_op, input_formats)
|
||||||
|
o_and_e('ebook-edit', tweak_op, tweak_formats)
|
||||||
|
o_and_w('fetch-ebook-metadata', fem_op, [])
|
||||||
|
o_and_w('calibre-smtp', smtp_op, [])
|
||||||
|
o_and_w('calibre-server', serv_op, [])
|
||||||
|
o_and_e('calibre-debug', debug_op, ['py', 'recipe', 'mobi', 'azw', 'azw3', 'docx'], file_map={
|
||||||
|
'--tweak-book':['epub', 'azw3', 'mobi'],
|
||||||
|
'--subset-font':['ttf', 'otf'],
|
||||||
|
'--exec-file':['py', 'recipe'],
|
||||||
|
'--add-simple-plugin':['py'],
|
||||||
|
'--inspect-mobi':['mobi', 'azw', 'azw3'],
|
||||||
|
'--viewer':list(available_input_formats()),
|
||||||
|
})
|
||||||
|
f.write(textwrap.dedent('''
|
||||||
|
_ebook_device_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="$(ebook-device ls ${search} 2>/dev/null)"
|
||||||
|
|
||||||
|
prefix="${search}"
|
||||||
|
if [[ "x${prefix:(-1)}" != "x/" ]]; then
|
||||||
|
prefix="${prefix}/"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo $(compgen -P "${prefix}" -W "${listing}" "${pattern}")
|
||||||
|
}
|
||||||
|
|
||||||
|
_ebook_device()
|
||||||
|
{
|
||||||
|
local cur prev
|
||||||
|
cur="${COMP_WORDS[COMP_CWORD]}"
|
||||||
|
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
||||||
|
COMPREPLY=()
|
||||||
|
case "${prev}" in
|
||||||
|
ls|rm|mkdir|touch|cat )
|
||||||
|
COMPREPLY=( $(_ebook_device_ls "${cur}") )
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
cp )
|
||||||
|
if [[ ${cur} == dev:* ]]; then
|
||||||
|
COMPREPLY=( $(_ebook_device_ls "${cur:7}") )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_filedir
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
dev )
|
||||||
|
COMPREPLY=( $(compgen -W "cp ls rm mkdir touch cat info books df" "${cur}") )
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
* )
|
||||||
|
if [[ ${cur} == dev:* ]]; then
|
||||||
|
COMPREPLY=( $(_ebook_device_ls "${cur:7}") )
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
if [[ ${prev} == dev:* ]]; then
|
||||||
|
_filedir
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
COMPREPLY=( $(compgen -W "dev:" "${cur}") )
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
complete -o nospace -F _ebook_device ebook-device
|
||||||
|
|
||||||
|
complete -o nospace -C %s ebook-convert
|
||||||
|
''')%complete)
|
||||||
|
# }}}
|
||||||
|
|
||||||
class PostInstall:
|
class PostInstall:
|
||||||
|
|
||||||
def task_failed(self, msg):
|
def task_failed(self, msg):
|
||||||
@ -539,151 +689,15 @@ class PostInstall:
|
|||||||
def setup_completion(self): # {{{
|
def setup_completion(self): # {{{
|
||||||
try:
|
try:
|
||||||
self.info('Setting up command-line completion...')
|
self.info('Setting up command-line completion...')
|
||||||
from calibre.ebooks.metadata.cli import option_parser as metaop, filetypes as meta_filetypes
|
|
||||||
from calibre.ebooks.lrf.lrfparser import option_parser as lrf2lrsop
|
|
||||||
from calibre.gui2.lrf_renderer.main import option_parser as lrfviewerop
|
|
||||||
from calibre.gui2.viewer.main import option_parser as viewer_op
|
|
||||||
from calibre.gui2.tweak_book.main import option_parser as tweak_op
|
|
||||||
from calibre.ebooks.metadata.sources.cli import option_parser as fem_op
|
|
||||||
from calibre.gui2.main import option_parser as guiop
|
|
||||||
from calibre.utils.smtp import option_parser as smtp_op
|
|
||||||
from calibre.library.server.main import option_parser as serv_op
|
|
||||||
from calibre.ebooks.oeb.polish.main import option_parser as polish_op, SUPPORTED
|
|
||||||
from calibre.ebooks.oeb.polish.import_book import IMPORTABLE
|
|
||||||
from calibre.debug import option_parser as debug_op
|
|
||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
|
||||||
from calibre.customize.ui import available_input_formats
|
|
||||||
input_formats = sorted(all_input_formats())
|
|
||||||
tweak_formats = sorted(x.lower() for x in SUPPORTED|IMPORTABLE)
|
|
||||||
zsh = ZshCompleter(self.opts)
|
zsh = ZshCompleter(self.opts)
|
||||||
bc = os.path.join(os.path.dirname(self.opts.staging_sharedir),
|
|
||||||
'bash-completion')
|
|
||||||
if os.path.exists(bc):
|
|
||||||
f = os.path.join(bc, 'calibre')
|
|
||||||
else:
|
|
||||||
if isnetbsd:
|
|
||||||
f = os.path.join(self.opts.staging_root, 'share/bash_completion.d/calibre')
|
|
||||||
else:
|
|
||||||
f = os.path.join(self.opts.staging_etc, 'bash_completion.d/calibre')
|
|
||||||
if not os.path.exists(os.path.dirname(f)):
|
|
||||||
os.makedirs(os.path.dirname(f))
|
|
||||||
bash_comp_dest, zsh_comp_dest = f, None
|
|
||||||
if zsh.dest:
|
if zsh.dest:
|
||||||
self.info('Installing zsh completion to:', zsh.dest)
|
self.info('Installing zsh completion to:', zsh.dest)
|
||||||
self.manifest.append(zsh.dest)
|
self.manifest.append(zsh.dest)
|
||||||
zsh_comp_dest = zsh.dest
|
bash_comp_dest = get_bash_completion_path(self.opts.staging_root, os.path.dirname(self.opts.staging_sharedir), self.info)
|
||||||
complete = 'calibre-complete'
|
if bash_comp_dest is not None:
|
||||||
if getattr(sys, 'frozen_path', None):
|
self.info('Installing bash completion to:', bash_comp_dest)
|
||||||
complete = os.path.join(getattr(sys, 'frozen_path'), complete)
|
self.manifest.append(bash_comp_dest)
|
||||||
|
write_completion(bash_comp_dest, zsh)
|
||||||
self.info('Installing bash completion to', f)
|
|
||||||
with open(f, 'wb') as f:
|
|
||||||
def o_and_e(*args, **kwargs):
|
|
||||||
f.write(opts_and_exts(*args, **kwargs))
|
|
||||||
zsh.opts_and_exts(*args, **kwargs)
|
|
||||||
def o_and_w(*args, **kwargs):
|
|
||||||
f.write(opts_and_words(*args, **kwargs))
|
|
||||||
zsh.opts_and_words(*args, **kwargs)
|
|
||||||
|
|
||||||
f.write('# calibre Bash Shell Completion\n')
|
|
||||||
o_and_e('calibre', guiop, BOOK_EXTENSIONS)
|
|
||||||
o_and_e('lrf2lrs', lrf2lrsop, ['lrf'], file_map={'--output':['lrs']})
|
|
||||||
o_and_e('ebook-meta', metaop,
|
|
||||||
list(meta_filetypes()), cover_opts=['--cover', '-c'],
|
|
||||||
opf_opts=['--to-opf', '--from-opf'])
|
|
||||||
o_and_e('ebook-polish', polish_op,
|
|
||||||
[x.lower() for x in SUPPORTED], cover_opts=['--cover', '-c'],
|
|
||||||
opf_opts=['--opf', '-o'])
|
|
||||||
o_and_e('lrfviewer', lrfviewerop, ['lrf'])
|
|
||||||
o_and_e('ebook-viewer', viewer_op, input_formats)
|
|
||||||
o_and_e('ebook-edit', tweak_op, tweak_formats)
|
|
||||||
o_and_w('fetch-ebook-metadata', fem_op, [])
|
|
||||||
o_and_w('calibre-smtp', smtp_op, [])
|
|
||||||
o_and_w('calibre-server', serv_op, [])
|
|
||||||
o_and_e('calibre-debug', debug_op, ['py', 'recipe', 'mobi', 'azw', 'azw3', 'docx'], file_map={
|
|
||||||
'--tweak-book':['epub', 'azw3', 'mobi'],
|
|
||||||
'--subset-font':['ttf', 'otf'],
|
|
||||||
'--exec-file':['py', 'recipe'],
|
|
||||||
'--add-simple-plugin':['py'],
|
|
||||||
'--inspect-mobi':['mobi', 'azw', 'azw3'],
|
|
||||||
'--viewer':list(available_input_formats()),
|
|
||||||
})
|
|
||||||
f.write(textwrap.dedent('''
|
|
||||||
_ebook_device_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="$(ebook-device ls ${search} 2>/dev/null)"
|
|
||||||
|
|
||||||
prefix="${search}"
|
|
||||||
if [[ "x${prefix:(-1)}" != "x/" ]]; then
|
|
||||||
prefix="${prefix}/"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo $(compgen -P "${prefix}" -W "${listing}" "${pattern}")
|
|
||||||
}
|
|
||||||
|
|
||||||
_ebook_device()
|
|
||||||
{
|
|
||||||
local cur prev
|
|
||||||
cur="${COMP_WORDS[COMP_CWORD]}"
|
|
||||||
prev="${COMP_WORDS[COMP_CWORD-1]}"
|
|
||||||
COMPREPLY=()
|
|
||||||
case "${prev}" in
|
|
||||||
ls|rm|mkdir|touch|cat )
|
|
||||||
COMPREPLY=( $(_ebook_device_ls "${cur}") )
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
cp )
|
|
||||||
if [[ ${cur} == dev:* ]]; then
|
|
||||||
COMPREPLY=( $(_ebook_device_ls "${cur:7}") )
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
_filedir
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
dev )
|
|
||||||
COMPREPLY=( $(compgen -W "cp ls rm mkdir touch cat info books df" "${cur}") )
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
* )
|
|
||||||
if [[ ${cur} == dev:* ]]; then
|
|
||||||
COMPREPLY=( $(_ebook_device_ls "${cur:7}") )
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
if [[ ${prev} == dev:* ]]; then
|
|
||||||
_filedir
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
COMPREPLY=( $(compgen -W "dev:" "${cur}") )
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
}
|
|
||||||
complete -o nospace -F _ebook_device ebook-device
|
|
||||||
|
|
||||||
complete -o nospace -C %s ebook-convert
|
|
||||||
''')%complete)
|
|
||||||
zsh.write()
|
|
||||||
self.manifest.extend((bash_comp_dest, zsh_comp_dest))
|
|
||||||
except TypeError as err:
|
except TypeError as err:
|
||||||
if 'resolve_entities' in str(err):
|
if 'resolve_entities' in str(err):
|
||||||
print 'You need python-lxml >= 2.0.5 for calibre'
|
print 'You need python-lxml >= 2.0.5 for calibre'
|
||||||
@ -692,6 +706,9 @@ class PostInstall:
|
|||||||
except EnvironmentError as e:
|
except EnvironmentError as e:
|
||||||
if e.errno == errno.EACCES:
|
if e.errno == errno.EACCES:
|
||||||
self.warning('Failed to setup completion, permission denied')
|
self.warning('Failed to setup completion, permission denied')
|
||||||
|
if self.opts.fatal_errors:
|
||||||
|
raise
|
||||||
|
self.task_failed('Setting up completion failed')
|
||||||
except:
|
except:
|
||||||
if self.opts.fatal_errors:
|
if self.opts.fatal_errors:
|
||||||
raise
|
raise
|
||||||
|
Loading…
x
Reference in New Issue
Block a user