# HG changeset patch # User Simon Farnsworth # Date 1457967687 0 # Node ID 71e12fc53b80180ca20e8192abf8ee4d70727fbe # Parent 4b81487a01d4bc69cc80607d7f05a3883d79875a 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.. 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. diff -r 4b81487a01d4 -r 71e12fc53b80 mercurial/help/config.txt --- 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. diff -r 4b81487a01d4 -r 71e12fc53b80 mercurial/ui.py --- 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? diff -r 4b81487a01d4 -r 71e12fc53b80 tests/test-commit-interactive-curses.t --- 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 <> $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 < 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 <> $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 <> $HGRCPATH + > [ui] + > interface = text + > interface.chunkselector = curses + > EOF + + $ chunkselectorinterface + curses + + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <> $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 <> $HGRCPATH + > [ui] + > interface = blah + > EOF + $ chunkselectorinterface + invalid value for ui.interface: blah (using text) + text + + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <> $HGRCPATH + > [ui] + > interface = curses + > interface.chunkselector = blah + > EOF + $ chunkselectorinterface + invalid value for ui.interface.chunkselector: blah (using curses) + curses + + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <> $HGRCPATH + > [ui] + > interface = blah + > interface.chunkselector = curses + > EOF + $ chunkselectorinterface + invalid value for ui.interface: blah + curses + + $ cp $HGRCPATH.pretest $HGRCPATH + $ cat <> $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