Mercurial > hg
changeset 28542:71e12fc53b80
ui: add new config flag for interface selection
This patch introduces a new config flag ui.interface to select the interface
for interactive commands. It currently only applies to chunks selection.
The config can be overridden on a per feature basis with the flag
ui.interface.<feature>.
features for the moment can only be 'chunkselector', moving forward we expect
to have 'histedit' and other commands there.
If an incorrect value is given to ui.interface we print a warning and use the
default interface: text. If HGPLAIN is specified we also use the default
interface: text.
Note that we fail quickly if a feature does not handle all the interfaces
that we permit in ui.interface; in future, we could design a fallback path
(e.g. blackpearl to curses, curses to text), but let's leave that until we
need it.
author | Simon Farnsworth <simonfar@fb.com> |
---|---|
date | Mon, 14 Mar 2016 15:01:27 +0000 |
parents | 4b81487a01d4 |
children | f7874de435c5 |
files | mercurial/help/config.txt mercurial/ui.py tests/test-commit-interactive-curses.t |
diffstat | 3 files changed, 168 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/help/config.txt Fri Mar 11 10:30:08 2016 +0000 +++ b/mercurial/help/config.txt Mon Mar 14 15:01:27 2016 +0000 @@ -1613,6 +1613,15 @@ ``interactive`` Allow to prompt the user. (default: True) +``interface`` + Select the default interface for interactive features (default: text). + Possible values are 'text' and 'curses'. + +``interface.chunkselector`` + Select the interface for change recording (e.g. :hg:`commit` -i). + Possible values are 'text' and 'curses'. + This config overrides the interface specified by ui.interface. + ``logtemplate`` Template string for commands that print changesets.
--- a/mercurial/ui.py Fri Mar 11 10:30:08 2016 +0000 +++ b/mercurial/ui.py Mon Mar 14 15:01:27 2016 +0000 @@ -697,6 +697,77 @@ return False return util.isatty(fh) + def interface(self, feature): + """what interface to use for interactive console features? + + The interface is controlled by the value of `ui.interface` but also by + the value of feature-specific configuration. For example: + + ui.interface.histedit = text + ui.interface.chunkselector = curses + + Here the features are "histedit" and "chunkselector". + + The configuration above means that the default interfaces for commands + is curses, the interface for histedit is text and the interface for + selecting chunk is crecord (the best curses interface available). + + Consider the following exemple: + ui.interface = curses + ui.interface.histedit = text + + Then histedit will use the text interface and chunkselector will use + the default curses interface (crecord at the moment). + """ + alldefaults = frozenset(["text", "curses"]) + + featureinterfaces = { + "chunkselector": [ + "text", + "curses", + ] + } + + # Feature-specific interface + if feature not in featureinterfaces.keys(): + # Programming error, not user error + raise ValueError("Unknown feature requested %s" % feature) + + availableinterfaces = frozenset(featureinterfaces[feature]) + if alldefaults > availableinterfaces: + # Programming error, not user error. We need a use case to + # define the right thing to do here. + raise ValueError( + "Feature %s does not handle all default interfaces" % + feature) + + if self.plain(): + return "text" + + # Default interface for all the features + defaultinterface = "text" + i = self.config("ui", "interface", None) + if i in alldefaults: + defaultinterface = i + + choseninterface = defaultinterface + f = self.config("ui", "interface.%s" % feature, None) + if f in availableinterfaces: + choseninterface = f + + if i is not None and defaultinterface != i: + if f is not None: + self.warn(_("invalid value for ui.interface: %s\n") % + (i,)) + else: + self.warn(_("invalid value for ui.interface: %s (using %s)\n") % + (i, choseninterface)) + if f is not None and choseninterface != f: + self.warn(_("invalid value for ui.interface.%s: %s (using %s)\n") % + (feature, f, choseninterface)) + + return choseninterface + def interactive(self): '''is interactive input allowed?
--- a/tests/test-commit-interactive-curses.t Fri Mar 11 10:30:08 2016 +0000 +++ b/tests/test-commit-interactive-curses.t Mon Mar 14 15:01:27 2016 +0000 @@ -1,5 +1,6 @@ Set up a repo + $ cp $HGRCPATH $HGRCPATH.pretest $ cat <<EOF >> $HGRCPATH > [ui] > interactive = true @@ -223,3 +224,90 @@ hello world +Check ui.interface logic for the chunkselector + +The default interface is text + $ cp $HGRCPATH.pretest $HGRCPATH + $ chunkselectorinterface() { + > python <<EOF + > from mercurial import hg, ui, parsers;\ + > repo = hg.repository(ui.ui(), ".");\ + > print repo.ui.interface("chunkselector") + > EOF + > } + $ chunkselectorinterface + text + +If only the default is set, we'll use that for the feature, too + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [ui] + > interface = curses + > EOF + $ chunkselectorinterface + curses + +It is possible to override the default interface with a feature specific +interface + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [ui] + > interface = text + > interface.chunkselector = curses + > EOF + + $ chunkselectorinterface + curses + + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [ui] + > interface = curses + > interface.chunkselector = text + > EOF + + $ chunkselectorinterface + text + +If a bad interface name is given, we use the default value (with a nice +error message to suggest that the configuration needs to be fixed) + + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [ui] + > interface = blah + > EOF + $ chunkselectorinterface + invalid value for ui.interface: blah (using text) + text + + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [ui] + > interface = curses + > interface.chunkselector = blah + > EOF + $ chunkselectorinterface + invalid value for ui.interface.chunkselector: blah (using curses) + curses + + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [ui] + > interface = blah + > interface.chunkselector = curses + > EOF + $ chunkselectorinterface + invalid value for ui.interface: blah + curses + + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <<EOF >> $HGRCPATH + > [ui] + > interface = blah + > interface.chunkselector = blah + > EOF + $ chunkselectorinterface + invalid value for ui.interface: blah + invalid value for ui.interface.chunkselector: blah (using text) + text