Submitter | Simon Farnsworth |
---|---|
Date | March 14, 2016, 3:47 p.m. |
Message ID | <5302c318da91dfa71853.1457970435@simonfar-macbookpro.local> |
Download | mbox | patch |
Permalink | /patch/13879/ |
State | Accepted |
Commit | 71e12fc53b80180ca20e8192abf8ee4d70727fbe |
Headers | show |
Comments
Augie, Pierre-Yves, you both had review comments on Laurent's V4 patch. Would you mind taking a look at this version? Thanks, Simon On 14/03/2016, 15:47, "Mercurial-devel on behalf of Simon Farnsworth" <mercurial-devel-bounces@mercurial-scm.org on behalf of simonfar@fb.com> wrote: ># HG changeset patch ># User Simon Farnsworth <simonfar@fb.com> ># Date 1457967687 0 ># Mon Mar 14 15:01:27 2016 +0000 ># Node ID 5302c318da91dfa7185389cf2e8e3f0685237030 ># Parent 70c2f8a982766b512e9d7f41f2d93fdb92f5481f >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. > >diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt >--- a/mercurial/help/config.txt >+++ b/mercurial/help/config.txt >@@ -1607,6 +1607,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 --git a/mercurial/ui.py b/mercurial/ui.py >--- a/mercurial/ui.py >+++ b/mercurial/ui.py >@@ -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 --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 <<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 >_______________________________________________ >Mercurial-devel mailing list >Mercurial-devel@mercurial-scm.org >https://urldefense.proofpoint.com/v2/url?u=https-3A__www.mercurial-2Dscm.org_mailman_listinfo_mercurial-2Ddevel&d=CwIGaQ&c=5VD0RTtNlTh3ycd41b3MUw&r=mEgSWILcY4c4W3zjApBQLA&m=SIjGp-B9f6VSxEYvTD3hENetZeSS3NNoKGvCELhRLBs&s=SFIrdP59am7CX7Ix-MNL4hoTsYvoQaZNMYeWbHKtrn0&e=
Patch
diff --git a/mercurial/help/config.txt b/mercurial/help/config.txt --- a/mercurial/help/config.txt +++ b/mercurial/help/config.txt @@ -1607,6 +1607,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 --git a/mercurial/ui.py b/mercurial/ui.py --- a/mercurial/ui.py +++ b/mercurial/ui.py @@ -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 --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 <<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