diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -1613,6 +1613,15 @@ User interface controls. ``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 --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -697,6 +697,77 @@ class ui(object): 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 --git a/tests/test-commit-interactive-curses.t b/tests/test-commit-interactive-curses.t --- a/tests/test-commit-interactive-curses.t +++ b/tests/test-commit-interactive-curses.t @@ -1,5 +1,6 @@ Set up a repo + $ cp $HGRCPATH $HGRCPATH.pretest $ cat <> $HGRCPATH > [ui] > interactive = true @@ -223,3 +224,90 @@ of the edit. 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