[PATCH] pager: disable pager for interactive prompts and subprocesses

Brodie Rao dackze at gmail.com
Wed Feb 11 16:59:59 CST 2009


Has anyone had a chance to look at this? I'd like comments if anyone  
has any.

Another approach was mentioned on the user mailing list: http://selenic.com/pipermail/mercurial/2009-February/023954.html 
  - I think it might be useful in conjunction with this.

One limitation of this implementation is that when the pager is  
killed, output that was previously paged is lost (unless the user's  
pager doesn't use the alternate buffer, e.g. less -X). I think it's  
still a huge improvement that the command doesn't get trashed by the  
pager.

Another case would be commands that aren't interactive but never  
return, like hg serve.

On Dec 11, 2008, at 10:54 AM, Brodie Rao wrote:

> # HG changeset patch
> # User Brodie Rao <me+hg at dackz.net>
> # Date 1228315940 18000
> # Node ID 65aac189ba9643367facf651b95302a06ef7d861
> # Parent  d8cd79fbed3c7b358dd820ff5dee44a7cff362bc
> pager: disable pager for interactive prompts and subprocesses
>
> diff --git a/hgext/pager.py b/hgext/pager.py
> --- a/hgext/pager.py
> +++ b/hgext/pager.py
> @@ -23,6 +23,9 @@ If no pager is set, the pager extensions
> variable $PAGER. If neither pager.pager, nor $PAGER is set, no pager
> is used.
>
> +If an interactive prompt or subprocess is opened by Mercurial, the  
> prompt
> +will appear when you exit the pager (and subsequent output will not  
> be paged).
> +
> If you notice "BROKEN PIPE" error messages, you can disable them
> by setting:
>
> @@ -49,16 +52,41 @@ them in the global .hgrc
> import sys, os, signal
> from mercurial import dispatch, util, extensions
>
> +def pagecmd(orig, ui, options, cmd, cmdfunc):
> +    # disable the pager for interactive prompts
> +    def wrapper(orig, *args, **kwargs):
> +        if sys.stdout != sys.__stdout__:
> +            sys.stdout.close()
> +            sys.stdout = sys.__stdout__
> +            sys.stderr = sys.__stderr__
> +        return orig(*args, **kwargs)
> +
> +    import __builtin__
> +    extensions.wrapfunction(__builtin__, 'input', wrapper)
> +    extensions.wrapfunction(__builtin__, 'raw_input', wrapper)
> +
> +    import getpass
> +    extensions.wrapfunction(getpass, 'getpass', wrapper)
> +
> +    from mercurial.ui import ui as uicls
> +    extensions.wrapfunction(uicls, 'prompt', wrapper)
> +    extensions.wrapfunction(uicls, 'getpass', wrapper)
> +
> +    # disable the pager if a subprocess is opened (like ssh)
> +    extensions.wrapfunction(util, 'system', wrapper)
> +    extensions.wrapfunction(util, 'popen', wrapper)
> +    extensions.wrapfunction(util, 'popen2', wrapper)
> +    extensions.wrapfunction(util, 'popen3', wrapper)
> +
> +    p = ui.config("pager", "pager", os.environ.get("PAGER"))
> +    if p and sys.stdout.isatty() and '--debugger' not in sys.argv:
> +        attend = ui.configlist('pager', 'attend')
> +        if (cmd in attend or
> +            (cmd not in ui.configlist('pager', 'ignore') and not  
> attend)):
> +            sys.stderr = sys.stdout = util.popen(p, "wb")
> +            if ui.configbool('pager', 'quiet'):
> +                signal.signal(signal.SIGPIPE, signal.SIG_DFL)
> +    return orig(ui, options, cmd, cmdfunc)
> +
> def uisetup(ui):
> -    def pagecmd(orig, ui, options, cmd, cmdfunc):
> -        p = ui.config("pager", "pager", os.environ.get("PAGER"))
> -        if p and sys.stdout.isatty() and '--debugger' not in  
> sys.argv:
> -            attend = ui.configlist('pager', 'attend')
> -            if (cmd in attend or
> -                (cmd not in ui.configlist('pager', 'ignore') and  
> not attend)):
> -                sys.stderr = sys.stdout = util.popen(p, "wb")
> -                if ui.configbool('pager', 'quiet'):
> -                    signal.signal(signal.SIGPIPE, signal.SIG_DFL)
> -        return orig(ui, options, cmd, cmdfunc)
> -
>     extensions.wrapfunction(dispatch, '_runcommand', pagecmd)



More information about the Mercurial-devel mailing list