[PATCH] Log, annotate and diff use an environment pager if available

David Soria Parra sn_ at gmx.net
Thu Mar 6 11:20:29 CST 2008


Okay I'll give it another try.

This time I'll changed also hgrc to document two new variables:
ui.pager can be used to override the default pager command and
ui.usepager can be used to disable the use of the pager at all, but
it defaults to True.

I also tried to improve the language in the comments:
(sorry but I'm not a native speaker)

--

# HG changeset patch
# User David Soria Parra <sn_ at gmx.net>
# Date 1204823969 -3600
# Node ID 4d398983852cbfb23965b47883f06946cbd9d79f
# Parent  0068809347d72e552f980487ee669ace9a82d214
Use the pager given by the environment to display long outputs

Unix systems usually have a PAGER environment variable set.
If it is set, mercurial will use this to display annotate, logs, diffs
or long help texts instead of just writing them to stdout.

Two configuration variables are available to influence the behaviour of the
pager. Using ui.pager you can override the pager given by $PAGER.
With ui.usepager you can disable the pager. The default is to use the pager.

diff -r 0068809347d7 -r 4d398983852c doc/hgrc.5.txt
--- a/doc/hgrc.5.txt	Fri Feb 29 14:48:21 2008 -0800
+++ b/doc/hgrc.5.txt	Thu Mar 06 18:19:29 2008 +0100
@@ -522,6 +522,12 @@
     Print debugging information.  True or False.  Default is False.
   editor;;
     The editor to use during a commit.  Default is $EDITOR or "vi".
+  pager;;
+    The pager that is used when displaying long output.
+    Default is $PAGER. If not set, the output is written to the
+    stdandard output.
+  usepager;;
+    If set to false, the pager is not used. True or False. Default is True.
   fallbackencoding;;
     Encoding to try if it's not possible to decode the changelog using
     UTF-8.  Default is ISO-8859-1.
diff -r 0068809347d7 -r 4d398983852c mercurial/cmdutil.py
--- a/mercurial/cmdutil.py	Fri Feb 29 14:48:21 2008 -0800
+++ b/mercurial/cmdutil.py	Thu Mar 06 18:19:29 2008 +0100
@@ -9,6 +9,7 @@
 from i18n import _
 import os, sys, bisect, stat
 import mdiff, bdiff, util, templater, templatefilters, patch, errno
+import ui.pager as pager

 revrangesep = ':'

@@ -558,6 +559,8 @@
     '''show changeset information when templating not requested.'''

     def __init__(self, ui, repo, patch, buffered):
+        self.pager = pager(ui)
+
         self.ui = ui
         self.repo = repo
         self.buffered = buffered
@@ -571,10 +574,10 @@
             h = self.header[rev]
             if h != self.lastheader:
                 self.lastheader = h
-                self.ui.write(h)
+                self.pager.write(h)
             del self.header[rev]
         if rev in self.hunk:
-            self.ui.write(self.hunk[rev])
+            self.pager.write(self.hunk[rev])
             del self.hunk[rev]
             return 1
         return 0
diff -r 0068809347d7 -r 4d398983852c mercurial/commands.py
--- a/mercurial/commands.py	Fri Feb 29 14:48:21 2008 -0800
+++ b/mercurial/commands.py	Thu Mar 06 18:19:29 2008 +0100
@@ -12,6 +12,7 @@
 import difflib, patch, time, help, mdiff, tempfile
 import errno, version, socket
 import archival, changegroup, cmdutil, hgweb.server, sshserver, hbisect
+import ui.pager as pager

 # Commands start here, listed alphabetically

@@ -919,12 +920,17 @@
     it detects as binary. With -a, diff will generate a diff anyway,
     probably with undesirable results.
     """
+    ui = pager(ui)
+    repo.ui = ui
+
     node1, node2 = cmdutil.revpair(repo, opts['rev'])
+

     fns, matchfn, anypats = cmdutil.matchpats(repo, pats, opts)

     patch.diff(repo, node1, node2, fns, match=matchfn,
                opts=patch.diffopts(ui, opts))
+

 def export(ui, repo, *changesets, **opts):
     """dump the header and diffs for one or more changesets
@@ -1226,6 +1232,7 @@
         doc = i[0].__doc__
         if not doc:
             doc = _("(No help text available)")
+
         if ui.quiet:
             doc = doc.splitlines(0)[0]
         ui.write("\n%s\n" % doc.rstrip())
@@ -1315,6 +1322,8 @@
         helplist(_('list of commands:\n\n'), modcmds.has_key)

     if name and name != 'shortlist':
+        # we use a pager when displaying long helptexts
+        ui = pager(ui)
         i = None
         for f in (helpcmd, helptopic, helpext):
             try:
diff -r 0068809347d7 -r 4d398983852c mercurial/ui.py
--- a/mercurial/ui.py	Fri Feb 29 14:48:21 2008 -0800
+++ b/mercurial/ui.py	Thu Mar 06 18:19:29 2008 +0100
@@ -1,6 +1,7 @@
 # ui.py - user interface bits for mercurial
 #
 # Copyright 2005-2007 Matt Mackall <mpm at selenic.com>
+# Copyright 2008 David Soria Parra <sn_ at gmx.net>
 #
 # This software may be used and distributed according to the terms
 # of the GNU General Public License, incorporated herein by reference.
@@ -478,3 +479,60 @@
                 os.environ.get("VISUAL") or
                 os.environ.get("EDITOR", "vi"))

+class pager(object):
+    """
+    Use the environment pager that is usually set on
+    UNIX like systems to display long outputs of e.g. hg log
+
+    The pager is not used if the output is not longer than min_lines
+    but instead prints the output to stdout.
+
+    As long as min_lines is not reached, every written line is
+    buffered. If min_lines is reached the buffer is flushed into the
+    pager pipe. After that every attemp to write is unbuffered, so that
+    the user gets the output faster and must not wait until
+    all ui.write operations finish
+    """
+    def __init__(self, ui, min_lines=25):
+        self.buffer = []
+        self.ui = ui
+        self.min_lines = min_lines
+
+    def __del__(self):
+        if len(self.buffer) < self.min_lines:
+            self.ui.write(os.linesep.join(self.buffer) + os.linesep)
+        elif self.proc:
+            try:
+                self.proc.close()
+            except IOError:
+                # we might get into an broken pipe if the users quit
+                # the pager before we finished io
+                pass
+
+    def __getattr__(self, key):
+        try:
+            return getattr(self.ui, key)
+        except AttributeError:
+            pass
+
+    def write(self, w):
+        self.buffer.extend(w.splitlines())
+        if len(self.buffer) >= self.min_lines and not self.buffer_written:
+            self.buffer_written = True
+            if self.getpager() and not self.proc:
+                self.proc = os.popen(self.getpager(), "w")
+                self.proc.write(os.linesep.join(self.buffer))
+            else:
+                self.ui.write(os.linesep.join(self.buffer))
+        elif self.buffer_written:
+            if self.proc:
+                self.proc.write(w)
+            else:
+                self.ui.write(w)
+
+    def getpager(self):
+        '''return a pager'''
+        if self.configbool("ui", "usepager", True):
+            return (self.config("ui", "pager")
+                    or os.environ.get("PAGER"))
+



More information about the Mercurial-devel mailing list