improved dialogs

main
Fabien Benureau 10 years ago
parent dd0475db46
commit 27a3058bee

@ -6,6 +6,8 @@ from .. import repo
from .. import paper from .. import paper
from .. import templates from .. import templates
from .. import apis from .. import apis
from .. import color
from .. import pretty
def parser(subparsers): def parser(subparsers):
@ -75,7 +77,7 @@ def command(args):
bibdata_raw = apis.doi2bibtex(args.doi) bibdata_raw = apis.doi2bibtex(args.doi)
bibdata = rp.databroker.verify(bibdata_raw) bibdata = rp.databroker.verify(bibdata_raw)
if bibdata is None: if bibdata is None:
ui.error('invalid doi {} or unable to retreive bibfile.'.format(args.doi)) ui.error('invalid doi {} or unable to retrieve bibfile.'.format(args.doi))
ui.exit(1) ui.exit(1)
# TODO distinguish between cases, offer to open the error page in a webbrowser. # TODO distinguish between cases, offer to open the error page in a webbrowser.
# TODO offer to confirm/change citekey # TODO offer to confirm/change citekey
@ -118,8 +120,9 @@ def command(args):
if docfile is not None: if docfile is not None:
rp.push_doc(p.citekey, docfile, copy=args.copy) rp.push_doc(p.citekey, docfile, copy=args.copy)
if args.copy: if args.copy:
if ui.input_yn('The file {} has been copied to the pubs repository. Should the original be removed?'.format(docfile)): if ui.input_yn('{} has been copied into pubs; should the original be removed?'.format(color.dye(docfile, color.bold))):
content.remove_file(docfile) content.remove_file(docfile)
ui.print_('{}\nwas added to pubs.'.format(pretty.paper_oneliner(p)))
except ValueError as v: except ValueError as v:
ui.error(v.message) ui.error(v.message)
ui.exit(1) ui.exit(1)

@ -1,4 +1,5 @@
from .. import repo from .. import repo
from .. import color
from ..configs import config from ..configs import config
from ..uis import get_ui from ..uis import get_ui
@ -30,6 +31,11 @@ def command(args):
try: try:
document = args.document document = args.document
document = rp.push_doc(paper.citekey, document, copy=args.copy) document = rp.push_doc(paper.citekey, document, copy=args.copy)
if args.copy:
if ui.input_yn('{} has been copied into pubs; should the original be removed?'.format(color.dye(document, color.bold))):
content.remove_file(docfile)
ui.print_('{} attached to {}'.format(color.dye(document, color.bold), color.dye(paper.citekey, color.citekey)))
except ValueError as v: except ValueError as v:
ui.error(v.message) ui.error(v.message)
ui.exit(1) ui.exit(1)

@ -48,12 +48,12 @@ class UI:
self._stdout = codecs.getwriter(self.encoding)(_get_raw_stdout(), self._stdout = codecs.getwriter(self.encoding)(_get_raw_stdout(),
errors='replace') errors='replace')
def print_(self, *strings): def print_(self, *strings, **kwargs):
"""Like print, but rather than raising an error when a character """Like print, but rather than raising an error when a character
is not in the terminal's encoding's character set, just silently is not in the terminal's encoding's character set, just silently
replaces it. replaces it.
""" """
print(' '.join(strings), file=self._stdout) print(' '.join(strings), file=self._stdout, **kwargs)
def input(self): def input(self):
try: try:
@ -63,6 +63,48 @@ class UI:
self.exit(1) self.exit(1)
return data return data
def input_choice_ng(self, options, option_chars=None, default=None, question=''):
"""Ask the user to chose between a set of options. The iser is asked
to input a char corresponding to the option he choses.
:param options: list of strings
list of options
:param default: int
default if no option is accepted, if None answer is required
:param question: string
:returns: int
the index of the chosen option
"""
char_color = color.bold
option_chars = [s[0] for s in options]
displayed_chars = [c.upper() if i == default else c
for i, c in enumerate(option_chars)]
if len(set(option_chars)) != len(option_chars): # duplicate chars, char choices are deactivated. #FIXME: should only deactivate ambiguous chars
option_chars = []
char_color = color.end
option_str = '/'.join(["{}{}".format(color.dye(c, color.bold), s[1:])
for c, s in zip(displayed_chars, options)])
self.print_('{} {}: '.format(question, option_str), end='')
while True:
answer = self.input()
if answer is None or answer == '':
if default is not None:
return default
else:
try:
return options.index(answer.lower())
except ValueError:
try: # FIXME options handling !!!
return option_chars.index(answer.lower())
except ValueError:
pass
self.print_('Incorrect option.', option_str)
def input_choice(self, options, option_chars, default=None, question=''): def input_choice(self, options, option_chars, default=None, question=''):
"""Ask the user to chose between a set of options. The iser is asked """Ask the user to chose between a set of options. The iser is asked
to input a char corresponding to the option he choses. to input a char corresponding to the option he choses.
@ -97,8 +139,8 @@ class UI:
def input_yn(self, question='', default='y'): def input_yn(self, question='', default='y'):
d = 0 if default in (True, 'y', 'yes') else 1 d = 0 if default in (True, 'y', 'yes') else 1
return (True, False)[self.input_choice(['yes', 'no'], ['y', 'n'], answer = self.input_choice_ng(['yes', 'no'], default=d, question=question)
default=d, question=question)] return [True, False][answer]
def exit(self, error_code=1): def exit(self, error_code=1):
sys.exit(error_code) sys.exit(error_code)

@ -1,22 +1,25 @@
# Function here may belong somewhere else. In the mean time... # Function here may belong somewhere else. In the mean time...
from . import color
def resolve_citekey(repo, citekey, ui=None, exit_on_fail=True): def resolve_citekey(repo, citekey, ui=None, exit_on_fail=True):
"""Check that a citekey exists, or autocompletes it if not ambiguous.""" """Check that a citekey exists, or autocompletes it if not ambiguous."""
# FIXME. Make me optionally non ui interactive/exiting # FIXME. Make me optionally non ui interactive/exiting
citekeys = repo.citekeys_from_prefix(citekey) citekeys = repo.citekeys_from_prefix(citekey)
if len(citekeys) == 0: if len(citekeys) == 0:
if ui is not None: if ui is not None:
ui.error("No citekey named or beginning with '{}".format(citekey)) ui.error("no citekey named or beginning with '{}'".format(color.dye(citekey, color.citekey)))
if exit_on_fail: if exit_on_fail:
ui.exit() ui.exit()
elif len(citekeys) == 1: elif len(citekeys) == 1:
if citekeys[0] != citekey: if citekeys[0] != citekey:
if ui is not None: if ui is not None:
ui.print_("Provided citekey '{}' has been autocompleted into '{}'".format(citekey, citekeys[0])) ui.warning("provided citekey '{}' has been autocompleted into '{}'".format(color.dye(citekey, color.citekey), color.dye(citekeys[0], color.citekey)))
citekey = citekeys[0] citekey = citekeys[0]
elif citekey not in citekeys: elif citekey not in citekeys:
if ui is not None: if ui is not None:
ui.error("Be more specific. Provided citekey '{}' matches multiples citekeys: {}".format(citekey, ', '.join(citekeys))) ui.error("be more specific; provided citekey '{}' matches multiples citekeys: {}".format(
citekey, ', '.join(color.dye(citekey, color.citekey) for citekey in citekeys)))
if exit_on_fail: if exit_on_fail:
ui.exit() ui.exit()
return citekey return citekey

Loading…
Cancel
Save