Patchwork [1,of,2] ui: add new config flag for interface selection

login
register
mail settings
Submitter Simon Farnsworth
Date March 10, 2016, 7:47 p.m.
Message ID <77d0ac209cc8555d887b.1457639257@SimonFar-MacBookPro.local>
Download mbox | patch
Permalink /patch/13745/
State Superseded
Commit 71e12fc53b80180ca20e8192abf8ee4d70727fbe
Headers show

Comments

Simon Farnsworth - March 10, 2016, 7:47 p.m.
# HG changeset patch
# User Simon Farnsworth <simonfar@fb.com>
# Date 1457639102 0
#      Thu Mar 10 19:45:02 2016 +0000
# Node ID 77d0ac209cc8555d887b35313fad25e947aab7fa
# Parent  1c658391b22fb4d98ccfb60c0e57315b55634117
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.
Simon Farnsworth - March 10, 2016, 8:34 p.m.
Scrub this - it fails tests.

I'm going to update patchwork, and resend on Monday when I've had a chance to recover from illness.

Simon





On 10/03/2016, 19: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 1457639102 0

>#      Thu Mar 10 19:45:02 2016 +0000

># Node ID 77d0ac209cc8555d887b35313fad25e947aab7fa

># Parent  1c658391b22fb4d98ccfb60c0e57315b55634117

>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,70 @@

>             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.issuperset(availableinterfaces):

>+            # Programming error, not user error

>+            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 is not None:

>+            if i not in allowedinterfaces:

>+                self.warn(_("invalid value for ui.interface: %s (using %s)\n")

>+                          % (i, defaultinterface))

>+            elif defaultinterface in availableinterfaces:

>+                defaultinterface = i

>+

>+        i = self.config("ui", "interface.%s" % feature, defaultinterface)

>+        if i in availableinterfaces:

>+            return i

>+        else:

>+            self.warn(_("invalid value for ui.interface.%s: %s (using %s)\n")

>+                      % (feature, i, defaultinterface))

>+            return defaultinterface

>+

>     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

>@@ -223,3 +223,58 @@

>   hello world

> 

> 

>+Check ui.interface logic for the chunkselector

>+

>+The default interface is text

>+  $ chunkselectorinterface() {

>+  > python <<EOF

>+  > from mercurial import hg, ui, parsers;\

>+  > repo = hg.repository(ui.ui(), ".");\

>+  > print repo.ui.interface("chunkselector")

>+  > EOF

>+  > }

>+  $ chunkselectorinterface

>+  text

>+

>+The default curses interface is crecord

>+  $ cat <<EOF >> $HGRCPATH

>+  > [ui]

>+  > interface = curses

>+  > EOF

>+  $ chunkselectorinterface

>+  crecord

>+

>+It is possible to override the default interface with a feature specific

>+interface

>+  $ cat <<EOF >> $HGRCPATH

>+  > [ui]

>+  > interface = text

>+  > interface.chunkselector = curses

>+  > EOF

>+

>+  $ chunkselectorinterface

>+  crecord

>+

>+If a bad interface name is given, we use the default value:

>+  $ cat <<EOF >> $HGRCPATH

>+  > [ui]

>+  > interface = curses

>+  > interface.chunkselector = blah

>+  > EOF

>+

>+  $ chunkselectorinterface

>+  invalid value for ui.interface.chunkselector: blah

>+  (using default interface instead: crecord)

>+  crecord

>+  $ cat <<EOF >> $HGRCPATH

>+  > [ui]

>+  > interface = blah

>+  > interface.chunkselector = blah

>+  > EOF

>+

>+  $ chunkselectorinterface

>+  invalid value for ui.interface: blah

>+  (using default interface instead text)

>+  invalid value for ui.interface.chunkselector: blah

>+  (using default interface instead: 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=rdj9ipfDjGSlMulLxM-k9rHLWDwWD9yrIRA6i0rtggs&s=LLTygIYKoi7C-x6bj3AE6gR1hsnEr1WoOrmjdpBri_I&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,70 @@ 
             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.issuperset(availableinterfaces):
+            # Programming error, not user error
+            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 is not None:
+            if i not in allowedinterfaces:
+                self.warn(_("invalid value for ui.interface: %s (using %s)\n")
+                          % (i, defaultinterface))
+            elif defaultinterface in availableinterfaces:
+                defaultinterface = i
+
+        i = self.config("ui", "interface.%s" % feature, defaultinterface)
+        if i in availableinterfaces:
+            return i
+        else:
+            self.warn(_("invalid value for ui.interface.%s: %s (using %s)\n")
+                      % (feature, i, defaultinterface))
+            return defaultinterface
+
     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
@@ -223,3 +223,58 @@ 
   hello world
 
 
+Check ui.interface logic for the chunkselector
+
+The default interface is text
+  $ chunkselectorinterface() {
+  > python <<EOF
+  > from mercurial import hg, ui, parsers;\
+  > repo = hg.repository(ui.ui(), ".");\
+  > print repo.ui.interface("chunkselector")
+  > EOF
+  > }
+  $ chunkselectorinterface
+  text
+
+The default curses interface is crecord
+  $ cat <<EOF >> $HGRCPATH
+  > [ui]
+  > interface = curses
+  > EOF
+  $ chunkselectorinterface
+  crecord
+
+It is possible to override the default interface with a feature specific
+interface
+  $ cat <<EOF >> $HGRCPATH
+  > [ui]
+  > interface = text
+  > interface.chunkselector = curses
+  > EOF
+
+  $ chunkselectorinterface
+  crecord
+
+If a bad interface name is given, we use the default value:
+  $ cat <<EOF >> $HGRCPATH
+  > [ui]
+  > interface = curses
+  > interface.chunkselector = blah
+  > EOF
+
+  $ chunkselectorinterface
+  invalid value for ui.interface.chunkselector: blah
+  (using default interface instead: crecord)
+  crecord
+  $ cat <<EOF >> $HGRCPATH
+  > [ui]
+  > interface = blah
+  > interface.chunkselector = blah
+  > EOF
+
+  $ chunkselectorinterface
+  invalid value for ui.interface: blah
+  (using default interface instead text)
+  invalid value for ui.interface.chunkselector: blah
+  (using default interface instead: text)
+  text