##// END OF EJS Templates
termwidth: move to ui.ui from util
termwidth: move to ui.ui from util

File last commit:

r12689:c52c629c default
r12689:c52c629c default
Show More
ui.py
622 lines | 22.5 KiB | text/x-python | PythonLexer
mpm@selenic.com
Move ui class to its own module...
r207 # ui.py - user interface bits for mercurial
#
Thomas Arendsen Hein
Updated copyright notices and add "and others" to "hg version"
r4635 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
mpm@selenic.com
Move ui class to its own module...
r207 #
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
mpm@selenic.com
Move ui class to its own module...
r207
Matt Mackall
Simplify i18n imports
r3891 from i18n import _
Martin Geisler
removed unused imports
r8656 import errno, getpass, os, socket, sys, tempfile, traceback
Simon Heimberg
separate import lines from mercurial and general python modules
r8312 import config, util, error
mpm@selenic.com
Move ui class to its own module...
r207
Eric Hopper
Convert all classes to new-style classes by deriving them from object.
r1559 class ui(object):
Matt Mackall
ui: kill most users of parentui name and arg, replace with .copy()
r8190 def __init__(self, src=None):
Matt Mackall
ui: buffers -> _buffers
r8202 self._buffers = []
Bryan O'Sullivan
Make it possible to debug failed hook imports via use of --traceback...
r9851 self.quiet = self.verbose = self.debugflag = self.tracebackflag = False
Matt Mackall
ui: make interactive a method
r8208 self._reportuntrusted = True
Matt Mackall
ui: privatize cdata vars
r8203 self._ocfg = config.config() # overlay
self._tcfg = config.config() # trusted
self._ucfg = config.config() # untrusted
Martin Geisler
ui: use set instead of dict
r8478 self._trustusers = set()
self._trustgroups = set()
Matt Mackall
ui: refactor option setting...
r8136
Matt Mackall
ui: kill most users of parentui name and arg, replace with .copy()
r8190 if src:
Matt Mackall
ui: privatize cdata vars
r8203 self._tcfg = src._tcfg.copy()
self._ucfg = src._ucfg.copy()
self._ocfg = src._ocfg.copy()
Matt Mackall
ui: trusted_users -> _trustusers, trusted_groups -> _trustgroups
r8201 self._trustusers = src._trustusers.copy()
self._trustgroups = src._trustgroups.copy()
Sune Foldager
ui: add environ property to access os.environ or wsgirequest.environ...
r9887 self.environ = src.environ
Matt Mackall
ui: simplify init, kill dupconfig
r8143 self.fixconfig()
else:
Sune Foldager
ui: add environ property to access os.environ or wsgirequest.environ...
r9887 # shared read-only environment
self.environ = os.environ
Alexis S. L. Carvalho
Use a variable to explicitly trust global config files
r3676 # we always trust global config files
Matt Mackall
ui: fold readsections into readconfig...
r8142 for f in util.rcpath():
Matt Mackall
ui: assumetrusted -> trust
r8200 self.readconfig(f, trust=True)
Dirkjan Ochtman
more whitespace cleanup and some other style nits
r8222
Matt Mackall
ui: replace parentui mechanism with repo.baseui
r8189 def copy(self):
Ronny Pfannschmidt
ui: ui.copy() now takes the ui class into account...
r8220 return self.__class__(self)
Thomas Arendsen Hein
Create local ui object per repository, so .hg/hgrc don't get mixed....
r1839
Matt Mackall
ui: cleanup _is_trusted a bit
r8141 def _is_trusted(self, fp, f):
Alexis S. L. Carvalho
Avoid looking up usernames if the current user owns the .hgrc file...
r3677 st = util.fstat(fp)
Martin Geisler
posix: do not use fstat in isowner...
r8657 if util.isowner(st):
Alexis S. L. Carvalho
Avoid looking up usernames if the current user owns the .hgrc file...
r3677 return True
Matt Mackall
ui: cleanup _is_trusted a bit
r8141
Matt Mackall
ui: trusted_users -> _trustusers, trusted_groups -> _trustgroups
r8201 tusers, tgroups = self._trustusers, self._trustgroups
Matt Mackall
ui: cleanup _is_trusted a bit
r8141 if '*' in tusers or '*' in tgroups:
return True
user = util.username(st.st_uid)
group = util.groupname(st.st_gid)
if user in tusers or group in tgroups or user == util.username():
return True
Matt Mackall
ui: report_untrusted fixes...
r8204 if self._reportuntrusted:
Matt Mackall
ui: cleanup _is_trusted a bit
r8141 self.warn(_('Not trusting file %s from untrusted '
'user %s, group %s\n') % (f, user, group))
return False
Alexis S. L. Carvalho
Only read .hg/hgrc files from trusted users/groups...
r3551
Matt Mackall
ui: assumetrusted -> trust
r8200 def readconfig(self, filename, root=None, trust=False,
Alexander Solovyov
hgwebdir: read --webdir-conf as actual configuration to ui (issue1586)...
r8345 sections=None, remap=None):
Matt Mackall
ui: fold readsections into readconfig...
r8142 try:
fp = open(filename)
except IOError:
if not sections: # ignore unless we were looking for something
return
raise
Matt Mackall
ui: always have ucdata...
r8139
Matt Mackall
ui: privatize cdata vars
r8203 cfg = config.config()
Matt Mackall
ui: assumetrusted -> trust
r8200 trusted = sections or trust or self._is_trusted(fp, filename)
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
Matt Mackall
ui: fold readsections into readconfig...
r8142 try:
Alexander Solovyov
hgwebdir: read --webdir-conf as actual configuration to ui (issue1586)...
r8345 cfg.read(filename, fp, sections=sections, remap=remap)
Matt Mackall
ui: introduce new config parser
r8144 except error.ConfigError, inst:
Matt Mackall
ui: fold readsections into readconfig...
r8142 if trusted:
Matt Mackall
ui: introduce new config parser
r8144 raise
self.warn(_("Ignored: %s\n") % str(inst))
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
Brodie Rao
ui: add HGPLAIN environment variable for easier scripting...
r10455 if self.plain():
Brodie Rao
ui: unset ui.slash when HGPLAIN is set
r10507 for k in ('debug', 'fallbackencoding', 'quiet', 'slash',
Yuya Nishihara
ui: ignore ui.logtemplate and ui.style when HGPLAIN is set...
r10567 'logtemplate', 'style',
Brodie Rao
ui: unset ui.slash when HGPLAIN is set
r10507 'traceback', 'verbose'):
Brodie Rao
ui: add HGPLAIN environment variable for easier scripting...
r10455 if k in cfg['ui']:
del cfg['ui'][k]
Brodie Rao
ui: suppress aliases when HGPLAIN is set
r10506 for k, v in cfg.items('alias'):
del cfg['alias'][k]
Brodie Rao
ui: add HGPLAIN environment variable for easier scripting...
r10455 for k, v in cfg.items('defaults'):
del cfg['defaults'][k]
Matt Mackall
ui: fold readsections into readconfig...
r8142 if trusted:
Matt Mackall
ui: privatize cdata vars
r8203 self._tcfg.update(cfg)
self._tcfg.update(self._ocfg)
self._ucfg.update(cfg)
self._ucfg.update(self._ocfg)
Matt Mackall
ui: always have ucdata...
r8139
Alexis S. L. Carvalho
ui.py: normalize settings every time the configuration changes...
r3347 if root is None:
root = os.path.expanduser('~')
self.fixconfig(root=root)
Alexis S. L. Carvalho
load extensions only after the ui object has been completely initialized...
r3014
Matt Mackall
ui: simplify fixconfig
r8197 def fixconfig(self, root=None):
Benoit Boissinot
ui.paths: expand paths directly in fixconfig (issue2373)...
r12662 # expand vars and ~
Alexis S. L. Carvalho
ui.py: normalize settings every time the configuration changes...
r3347 # translate paths relative to root (or home) into absolute paths
Matt Mackall
ui: simplify fixconfig
r8197 root = root or os.getcwd()
Matt Mackall
ui: privatize cdata vars
r8203 for c in self._tcfg, self._ucfg, self._ocfg:
Matt Mackall
ui: simplify fixconfig
r8197 for n, p in c.items('paths'):
Benoit Boissinot
ui.paths: expand paths directly in fixconfig (issue2373)...
r12662 if not p:
continue
if '%%' in p:
self.warn(_("(deprecated '%%' in path %s=%s from %s)\n")
% (n, p, self.configsource('paths', n)))
p = p.replace('%%', '%')
p = util.expandpath(p)
if '://' not in p and not os.path.isabs(p):
Benoit Boissinot
fix indentation error
r12665 p = os.path.normpath(os.path.join(root, p))
Benoit Boissinot
ui.paths: expand paths directly in fixconfig (issue2373)...
r12662 c.set("paths", n, p)
Alexis S. L. Carvalho
ui.py: normalize settings every time the configuration changes...
r3347
Matt Mackall
ui: fold verbosity_constraints into fixconfig, simplify
r8138 # update ui options
Matt Mackall
ui: simplify fixconfig
r8197 self.debugflag = self.configbool('ui', 'debug')
self.verbose = self.debugflag or self.configbool('ui', 'verbose')
self.quiet = not self.debugflag and self.configbool('ui', 'quiet')
if self.verbose and self.quiet:
self.quiet = self.verbose = False
Matt Mackall
ui: report_untrusted fixes...
r8204 self._reportuntrusted = self.configbool("ui", "report_untrusted", True)
Bryan O'Sullivan
Make it possible to debug failed hook imports via use of --traceback...
r9851 self.tracebackflag = self.configbool('ui', 'traceback', False)
Alexis S. L. Carvalho
update ui.quiet/verbose/debug/interactive every time the config changes...
r3350
Alexis S. L. Carvalho
Only read .hg/hgrc files from trusted users/groups...
r3551 # update trust information
Martin Geisler
ui: use set instead of dict
r8478 self._trustusers.update(self.configlist('trusted', 'users'))
self._trustgroups.update(self.configlist('trusted', 'groups'))
Alexis S. L. Carvalho
Only read .hg/hgrc files from trusted users/groups...
r3551
Mads Kiilerich
mq: don't inherit default and default-push paths with --mq (issue2333)...
r11965 def setconfig(self, section, name, value, overlay=True):
if overlay:
self._ocfg.set(section, name, value)
self._tcfg.set(section, name, value)
self._ucfg.set(section, name, value)
Matt Mackall
ui: simplify fixconfig
r8197 self.fixconfig()
mpm@selenic.com
Add ui.setconfig overlay...
r960
Matt Mackall
ui: _get_cdata -> _data
r8199 def _data(self, untrusted):
Matt Mackall
ui: privatize cdata vars
r8203 return untrusted and self._ucfg or self._tcfg
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
Matt Mackall
showconfig: show source file and line with --debug
r8182 def configsource(self, section, name, untrusted=False):
Matt Mackall
ui: _get_cdata -> _data
r8199 return self._data(untrusted).source(section, name) or 'none'
Matt Mackall
showconfig: show source file and line with --debug
r8182
Matt Mackall
ui: introduce new config parser
r8144 def config(self, section, name, default=None, untrusted=False):
Matt Mackall
ui: _get_cdata -> _data
r8199 value = self._data(untrusted).get(section, name, default)
Matt Mackall
ui: report_untrusted fixes...
r8204 if self.debugflag and not untrusted and self._reportuntrusted:
Matt Mackall
ui: privatize cdata vars
r8203 uvalue = self._ucfg.get(section, name)
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 if uvalue is not None and uvalue != value:
Matt Mackall
ui: report_untrusted fixes...
r8204 self.debug(_("ignoring untrusted configuration option "
Dirkjan Ochtman
more whitespace cleanup and some other style nits
r8222 "%s.%s = %s\n") % (section, name, uvalue))
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 return value
Alexis S. L. Carvalho
ui.py: move common code out of config and configbool
r3341
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 def configbool(self, section, name, default=False, untrusted=False):
Matt Mackall
ui: introduce new config parser
r8144 v = self.config(section, name, None, untrusted)
Martin Geisler
use 'x is None' instead of 'x == None'...
r8527 if v is None:
Matt Mackall
ui: introduce new config parser
r8144 return default
Dirkjan Ochtman
ui: just return it if it's already a bool
r10243 if isinstance(v, bool):
return v
Augie Fackler
parsebool: create new function and use it for config parsing
r12087 b = util.parsebool(v)
if b is None:
Matt Mackall
ui: introduce new config parser
r8144 raise error.ConfigError(_("%s.%s not a boolean ('%s')")
% (section, name, v))
Augie Fackler
parsebool: create new function and use it for config parsing
r12087 return b
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
def configlist(self, section, name, default=None, untrusted=False):
Thomas Arendsen Hein
Added ui.configlist method to get comma/space separated lists of strings....
r2499 """Return a list of comma/space separated strings"""
Henrik Stuart
ui: support quotes in configlist (issue2147)...
r10982
def _parse_plain(parts, s, offset):
whitespace = False
while offset < len(s) and (s[offset].isspace() or s[offset] == ','):
whitespace = True
offset += 1
if offset >= len(s):
return None, parts, offset
if whitespace:
parts.append('')
if s[offset] == '"' and not parts[-1]:
return _parse_quote, parts, offset + 1
elif s[offset] == '"' and parts[-1][-1] == '\\':
parts[-1] = parts[-1][:-1] + s[offset]
return _parse_plain, parts, offset + 1
parts[-1] += s[offset]
return _parse_plain, parts, offset + 1
def _parse_quote(parts, s, offset):
if offset < len(s) and s[offset] == '"': # ""
parts.append('')
offset += 1
while offset < len(s) and (s[offset].isspace() or
s[offset] == ','):
offset += 1
return _parse_plain, parts, offset
while offset < len(s) and s[offset] != '"':
Henrik Stuart
ui: fix check-code error
r11036 if (s[offset] == '\\' and offset + 1 < len(s)
and s[offset + 1] == '"'):
Henrik Stuart
ui: support quotes in configlist (issue2147)...
r10982 offset += 1
parts[-1] += '"'
else:
parts[-1] += s[offset]
offset += 1
if offset >= len(s):
real_parts = _configlist(parts[-1])
if not real_parts:
parts[-1] = '"'
else:
real_parts[0] = '"' + real_parts[0]
parts = parts[:-1]
parts.extend(real_parts)
return None, parts, offset
offset += 1
while offset < len(s) and s[offset] in [' ', ',']:
offset += 1
if offset < len(s):
if offset + 1 == len(s) and s[offset] == '"':
parts[-1] += '"'
offset += 1
else:
parts.append('')
else:
return None, parts, offset
return _parse_plain, parts, offset
def _configlist(s):
s = s.rstrip(' ,')
if not s:
Alecs King
ui: differentiate empty configlist from None
r11945 return []
Henrik Stuart
ui: support quotes in configlist (issue2147)...
r10982 parser, parts, offset = _parse_plain, [''], 0
while parser:
parser, parts, offset = parser(parts, s, offset)
return parts
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 result = self.config(section, name, untrusted=untrusted)
Thomas Arendsen Hein
Added ui.configlist method to get comma/space separated lists of strings....
r2499 if result is None:
Thomas Arendsen Hein
Allow using default values with ui.configlist, too, and add a test for this.
r2502 result = default or []
if isinstance(result, basestring):
Thomas Arendsen Hein
ui: handle leading newlines/spaces/commas in configlist...
r11309 result = _configlist(result.lstrip(' ,\n'))
Henrik Stuart
ui: support quotes in configlist (issue2147)...
r10982 if result is None:
result = default or []
Thomas Arendsen Hein
Allow using default values with ui.configlist, too, and add a test for this.
r2502 return result
Thomas Arendsen Hein
Added ui.configlist method to get comma/space separated lists of strings....
r2499
Bryan O'Sullivan
ui: Rename has_config to has_section.
r4487 def has_section(self, section, untrusted=False):
Vadim Gelfer
add ui.has_config method.
r2343 '''tell whether section exists in config.'''
Matt Mackall
ui: _get_cdata -> _data
r8199 return section in self._data(untrusted)
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552
def configitems(self, section, untrusted=False):
Matt Mackall
ui: _get_cdata -> _data
r8199 items = self._data(untrusted).items(section)
Matt Mackall
ui: report_untrusted fixes...
r8204 if self.debugflag and not untrusted and self._reportuntrusted:
Dirkjan Ochtman
more whitespace cleanup and some other style nits
r8222 for k, v in self._ucfg.items(section):
Matt Mackall
ui: privatize cdata vars
r8203 if self._tcfg.get(section, k) != v:
Matt Mackall
ui: report_untrusted fixes...
r8204 self.debug(_("ignoring untrusted configuration option "
Matt Mackall
ui: introduce new config parser
r8144 "%s.%s = %s\n") % (section, k, v))
return items
mpm@selenic.com
ui: add configuration file support...
r285
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 def walkconfig(self, untrusted=False):
Matt Mackall
ui: privatize cdata vars
r8203 cfg = self._data(untrusted)
for section in cfg.sections():
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 for name, value in self.configitems(section, untrusted):
Alexis S. L. Carvalho
Fix hg showconfig traceback with values that aren't strings
r4085 yield section, name, str(value).replace('\n', '\\n')
Bryan O'Sullivan
Add commands.debugconfig....
r1028
Brodie Rao
ui: add HGPLAIN environment variable for easier scripting...
r10455 def plain(self):
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325 '''is plain mode active?
Plain mode means that all configuration variables which affect the
behavior and output of Mercurial should be ignored. Additionally, the
output should be stable, reproducible and suitable for use in scripts or
applications.
The only way to trigger plain mode is by setting the `HGPLAIN'
environment variable.
'''
Brodie Rao
ui: add HGPLAIN environment variable for easier scripting...
r10455 return 'HGPLAIN' in os.environ
Matt Mackall
Add username/merge/editor to .hgrc...
r608 def username(self):
Thomas Arendsen Hein
Adapted behaviour of ui.username() to documentation and mention it explicitly:...
r1985 """Return default username to be used in commits.
Searched in this order: $HGUSER, [ui] section of hgrcs, $EMAIL
and stop searching if one of these is set.
Benoit Boissinot
ui: add an option to prompt for the username when it isn't provided...
r6862 If not found and ui.askusername is True, ask the user, else use
($LOGNAME or $USER or $LNAME or $USERNAME) + "@full.hostname".
Thomas Arendsen Hein
Adapted behaviour of ui.username() to documentation and mention it explicitly:...
r1985 """
user = os.environ.get("HGUSER")
if user is None:
user = self.config("ui", "username")
Chad Dombrova
ui.username(): expand environment variables in username configuration value....
r11225 if user is not None:
user = os.path.expandvars(user)
Thomas Arendsen Hein
Adapted behaviour of ui.username() to documentation and mention it explicitly:...
r1985 if user is None:
user = os.environ.get("EMAIL")
Benoit Boissinot
ui: add an option to prompt for the username when it isn't provided...
r6862 if user is None and self.configbool("ui", "askusername"):
Martin Geisler
lowercase prompts...
r7600 user = self.prompt(_("enter a commit username:"), default=None)
Martin Geisler
ui: only use "user@host" as username in noninteractive mode...
r9613 if user is None and not self.interactive():
Benoit Boissinot
only print a warning when no username is specified...
r3721 try:
user = '%s@%s' % (util.getuser(), socket.getfqdn())
Thomas Arendsen Hein
Abort on empty username so specifying a username can be forced....
r4044 self.warn(_("No username found, using '%s' instead\n") % user)
Benoit Boissinot
only print a warning when no username is specified...
r3721 except KeyError:
Thomas Arendsen Hein
Abort on empty username so specifying a username can be forced....
r4044 pass
if not user:
Martin Geisler
ui: refer to "hg help config" when no username is set
r9786 raise util.Abort(_('no username supplied (see "hg help config")'))
Matt Mackall
ui: disallow newlines in usernames (issue1034)
r6351 if "\n" in user:
Benoit Boissinot
use repr() instead of backticks
r7470 raise util.Abort(_("username %s contains a newline\n") % repr(user))
Thomas Arendsen Hein
Adapted behaviour of ui.username() to documentation and mention it explicitly:...
r1985 return user
Matt Mackall
Add username/merge/editor to .hgrc...
r608
Thomas Arendsen Hein
Move generating short username to display in hg/hgweb annotate to ui module.
r1129 def shortuser(self, user):
"""Return a short representation of a user name or email address."""
Matt Mackall
many, many trivial check-code fixups
r10282 if not self.verbose:
user = util.shortuser(user)
Thomas Arendsen Hein
Move generating short username to display in hg/hgweb annotate to ui module.
r1129 return user
Vadim Gelfer
push, outgoing, bundle: fall back to "default" if "default-push" not defined
r2494 def expandpath(self, loc, default=None):
Thomas Arendsen Hein
Directory names take precedence over symbolic names consistently....
r1892 """Return repository location relative to cwd or from [paths]"""
Thomas Arendsen Hein
Only hg repositories override [paths], not simple directories (fixes issue510)
r4216 if "://" in loc or os.path.isdir(os.path.join(loc, '.hg')):
Thomas Arendsen Hein
Directory names take precedence over symbolic names consistently....
r1892 return loc
Benoit Boissinot
ui.paths: expand paths directly in fixconfig (issue2373)...
r12662 path = self.config('paths', loc)
Vadim Gelfer
make ui.expandpath better with default path.
r2495 if not path and default is not None:
Benoit Boissinot
ui.paths: expand paths directly in fixconfig (issue2373)...
r12662 path = self.config('paths', default)
Thomas Arendsen Hein
Fix ui.expandpath problem and broken test introduced by 4a2a4d988ead.
r2498 return path or loc
mpm@selenic.com
[PATCH] Add ui.expandpath command...
r506
Matt Mackall
add a simple nested buffering scheme to ui
r3737 def pushbuffer(self):
Matt Mackall
ui: buffers -> _buffers
r8202 self._buffers.append([])
Matt Mackall
add a simple nested buffering scheme to ui
r3737
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def popbuffer(self, labeled=False):
'''pop the last buffer and return the buffered output
If labeled is True, any labels associated with buffered
output will be handled. By default, this has no effect
on the output returned, but extensions and GUI tools may
handle this argument and returned styled output. If output
is being buffered so it can be captured and parsed or
processed, labeled should not be set to True.
'''
Matt Mackall
ui: buffers -> _buffers
r8202 return "".join(self._buffers.pop())
Matt Mackall
add a simple nested buffering scheme to ui
r3737
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def write(self, *args, **opts):
'''write args to output
By default, this method simply writes to the buffer or stdout,
but extensions or GUI tools may override this method,
write_err(), popbuffer(), and label() to style output from
various parts of hg.
An optional keyword argument, "label", can be passed in.
This should be a string containing label names separated by
space. Label names take the form of "topic.type". For example,
ui.debug() issues a label of "ui.debug".
When labeling output for a specific command, a label of
"cmdname.type" is recommended. For example, status issues
a label of "status.modified" for modified files.
'''
Matt Mackall
ui: buffers -> _buffers
r8202 if self._buffers:
self._buffers[-1].extend([str(a) for a in args])
Matt Mackall
add a simple nested buffering scheme to ui
r3737 else:
for a in args:
sys.stdout.write(str(a))
mpm@selenic.com
[PATCH] Make ui.warn write to stderr...
r565
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def write_err(self, *args, **opts):
Benoit Boissinot
ignore EPIPE in ui.err_write...
r1989 try:
Thomas Arendsen Hein
ui: look before you leap on sys.stderr.closed (and look nicer)...
r10421 if not getattr(sys.stdout, 'closed', False):
Matt Mackall
many, many trivial check-code fixups
r10282 sys.stdout.flush()
Benoit Boissinot
ignore EPIPE in ui.err_write...
r1989 for a in args:
sys.stderr.write(str(a))
Patrick Mezard
Flush stderr after write....
r4023 # stderr may be buffered under win32 when redirected to files,
# including stdout.
Thomas Arendsen Hein
ui: look before you leap on sys.stderr.closed (and look nicer)...
r10421 if not getattr(sys.stderr, 'closed', False):
Matt Mackall
many, many trivial check-code fixups
r10282 sys.stderr.flush()
Benoit Boissinot
ignore EPIPE in ui.err_write...
r1989 except IOError, inst:
Mads Kiilerich
ui: ignore EIO in write_err...
r11416 if inst.errno not in (errno.EPIPE, errno.EIO):
Benoit Boissinot
ignore EPIPE in ui.err_write...
r1989 raise
mpm@selenic.com
[PATCH] Make ui.warn write to stderr...
r565
Vadim Gelfer
make ui flush output. this makes error happen if printing to /dev/full....
r1837 def flush(self):
Eung-Ju Park
Fix error on Windows if "hg log | more" exits.
r2013 try: sys.stdout.flush()
except: pass
try: sys.stderr.flush()
except: pass
Vadim Gelfer
make ui flush output. this makes error happen if printing to /dev/full....
r1837
Matt Mackall
ui: make interactive a method
r8208 def interactive(self):
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325 '''is interactive input allowed?
An interactive session is a session where input can be reasonably read
from `sys.stdin'. If this function returns false, any attempt to read
from stdin should fail with an error, unless a sensible default has been
specified.
Interactiveness is triggered by the value of the `ui.interactive'
configuration variable or - if it is unset - when `sys.stdin' points
to a terminal device.
This function refers to input only; for output, see `ui.formatted()'.
'''
Patrick Mezard
ui: honor interactive=off even if isatty()
r8538 i = self.configbool("ui", "interactive", None)
if i is None:
Ronny Pfannschmidt
make ui.interactive() return false in case stdin lacks isatty
r10077 try:
return sys.stdin.isatty()
except AttributeError:
# some environments replace stdin without implementing isatty
# usually those are non-interactive
return False
Patrick Mezard
ui: honor interactive=off even if isatty()
r8538 return i
Matt Mackall
ui: make interactive a method
r8208
Augie Fackler
termwidth: move to ui.ui from util
r12689 def termwidth(self):
'''how wide is the terminal in columns?
'''
if 'COLUMNS' in os.environ:
try:
return int(os.environ['COLUMNS'])
except ValueError:
pass
return util.termwidth()
Dan Villiom Podlaski Christiansen
ui: add ui.formatted configuration variable and accessor function....
r11324 def formatted(self):
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325 '''should formatted output be used?
It is often desirable to format the output to suite the output medium.
Examples of this are truncating long lines or colorizing messages.
However, this is not often not desirable when piping output into other
utilities, e.g. `grep'.
Formatted output is triggered by the value of the `ui.formatted'
configuration variable or - if it is unset - when `sys.stdout' points
to a terminal device. Please note that `ui.formatted' should be
considered an implementation detail; it is not intended for use outside
Mercurial or its extensions.
This function refers to output only; for input, see `ui.interactive()'.
This function always returns false when in plain mode, see `ui.plain()'.
'''
Dan Villiom Podlaski Christiansen
ui: add ui.formatted configuration variable and accessor function....
r11324 if self.plain():
return False
i = self.configbool("ui", "formatted", None)
if i is None:
try:
return sys.stdout.isatty()
except AttributeError:
# some environments replace stdout without implementing isatty
# usually those are non-interactive
return False
return i
Dirkjan Ochtman
Don't try to determine interactivity if ui() called with interactive=False....
r5337 def _readline(self, prompt=''):
Matt Mackall
ui: make interactive a method
r8208 if sys.stdin.isatty():
Bryan O'Sullivan
ui: get readline and prompt to behave better depending on interactivity
r5036 try:
# magically add command line editing support, where
# available
import readline
# force demandimport to really load the module
readline.read_history_file
Brendan Cully
issue1419: catch strange readline import error on windows
r7496 # windows sometimes raises something other than ImportError
except Exception:
Bryan O'Sullivan
ui: get readline and prompt to behave better depending on interactivity
r5036 pass
Steve Borho
workaround for raw_input() on Windows...
r5613 line = raw_input(prompt)
# When stdin is in binary mode on Windows, it can cause
# raw_input() to emit an extra trailing carriage return
if os.linesep == '\r\n' and line and line[-1] == '\r':
line = line[:-1]
return line
Bryan O'Sullivan
ui: get readline and prompt to behave better depending on interactivity
r5036
Simon Heimberg
ui: extract choice from prompt...
r9048 def prompt(self, msg, default="y"):
"""Prompt user with msg, read response.
If ui is not interactive, the default is returned.
Kirill Smelkov
prompt: kill matchflags...
r5751 """
Matt Mackall
ui: make interactive a method
r8208 if not self.interactive():
Mads Kiilerich
ui.prompt: Show prompt and selection in non-interactive mode...
r8940 self.write(msg, ' ', default, "\n")
Peter Arrenbrecht
ui: log non-interactive default response to stdout when verbose...
r7320 return default
Simon Heimberg
ui: extract choice from prompt...
r9048 try:
r = self._readline(msg + ' ')
if not r:
return default
return r
except EOFError:
raise util.Abort(_('response expected'))
def promptchoice(self, msg, choices, default=0):
"""Prompt user with msg, read response, and ensure it matches
one of the provided choices. The index of the choice is returned.
choices is a sequence of acceptable responses with the format:
Dirkjan Ochtman
kill trailing whitespace
r9312 ('&None', 'E&xec', 'Sym&link') Responses are case insensitive.
Simon Heimberg
ui: extract choice from prompt...
r9048 If ui is not interactive, the default is returned.
"""
resps = [s[s.index('&')+1].lower() for s in choices]
Thomas Arendsen Hein
Make ui.prompt repeat on "unrecognized response" again (issue897)...
r5671 while True:
Simon Heimberg
ui: extract choice from prompt...
r9048 r = self.prompt(msg, resps[default])
if r.lower() in resps:
return resps.index(r.lower())
self.write(_("unrecognized response\n"))
Vadim Gelfer
prompt user for http authentication info...
r2281 def getpass(self, prompt=None, default=None):
Matt Mackall
many, many trivial check-code fixups
r10282 if not self.interactive():
return default
Steve Borho
catch CTRL-D at password prompt...
r7798 try:
return getpass.getpass(prompt or _('password: '))
except EOFError:
raise util.Abort(_('response expected'))
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def status(self, *msg, **opts):
'''write status message to output (if ui.quiet is False)
This adds an output label of "ui.status".
'''
Matt Mackall
many, many trivial check-code fixups
r10282 if not self.quiet:
Brodie Rao
ui: add ui.write() output labeling API...
r10815 opts['label'] = opts.get('label', '') + ' ui.status'
self.write(*msg, **opts)
def warn(self, *msg, **opts):
'''write warning message to output (stderr)
This adds an output label of "ui.warning".
'''
opts['label'] = opts.get('label', '') + ' ui.warning'
self.write_err(*msg, **opts)
def note(self, *msg, **opts):
'''write note to output (if ui.verbose is True)
This adds an output label of "ui.note".
'''
Matt Mackall
many, many trivial check-code fixups
r10282 if self.verbose:
Brodie Rao
ui: add ui.write() output labeling API...
r10815 opts['label'] = opts.get('label', '') + ' ui.note'
self.write(*msg, **opts)
def debug(self, *msg, **opts):
'''write debug message to output (if ui.debugflag is True)
This adds an output label of "ui.debug".
'''
Matt Mackall
many, many trivial check-code fixups
r10282 if self.debugflag:
Brodie Rao
ui: add ui.write() output labeling API...
r10815 opts['label'] = opts.get('label', '') + ' ui.debug'
self.write(*msg, **opts)
Thomas Arendsen Hein
Pass correct username as $HGUSER to hgeditor if "commit -u" is used....
r1983 def edit(self, text, user):
Stephen Darnell
Use text rather than binary mode for editing commit messages
r2206 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt",
text=True)
Thomas Arendsen Hein
Improved ui.edit():...
r1984 try:
f = os.fdopen(fd, "w")
f.write(text)
f.close()
Osku Salerma
Use VISUAL in addition to EDITOR when choosing the editor to use.
r5660 editor = self.geteditor()
mpm@selenic.com
Move ui class to its own module...
r207
Thomas Arendsen Hein
Improved ui.edit():...
r1984 util.system("%s \"%s\"" % (editor, name),
environ={'HGUSER': user},
onerr=util.Abort, errprefix=_("edit failed"))
Matt Mackall
Add username/merge/editor to .hgrc...
r608
Thomas Arendsen Hein
Improved ui.edit():...
r1984 f = open(name)
t = f.read()
f.close()
finally:
os.unlink(name)
Radoslaw "AstralStorm" Szkodzinski
Pass username to hgeditor, remove temporary file...
r662
mpm@selenic.com
Move ui class to its own module...
r207 return t
Vadim Gelfer
move mail sending code into core, so extensions can share it....
r2200
Bryan O'Sullivan
Make it possible to debug failed hook imports via use of --traceback...
r9851 def traceback(self, exc=None):
Vadim Gelfer
add ui.print_exc(), make all traceback printing central.
r2335 '''print exception traceback if traceback printing enabled.
only to call in exception handler. returns true if traceback
printed.'''
Bryan O'Sullivan
Make it possible to debug failed hook imports via use of --traceback...
r9851 if self.tracebackflag:
if exc:
traceback.print_exception(exc[0], exc[1], exc[2])
else:
traceback.print_exc()
return self.tracebackflag
Osku Salerma
Use VISUAL in addition to EDITOR when choosing the editor to use.
r5660
def geteditor(self):
'''return editor to use'''
return (os.environ.get("HGEDITOR") or
self.config("ui", "editor") or
os.environ.get("VISUAL") or
os.environ.get("EDITOR", "vi"))
Matt Mackall
Add ui.progress API
r9153
def progress(self, topic, pos, item="", unit="", total=None):
'''show a progress message
With stock hg, this is simply a debug message that is hidden
by default, but with extensions or GUI tools it may be
visible. 'topic' is the current operation, 'item' is a
non-numeric marker of the current position (ie the currently
in-process file), 'pos' is the current numeric position (ie
Brodie Rao
ui: fix NameError in ui.progress due to unit/units typo
r9398 revision, bytes, etc.), unit is a corresponding unit label,
Matt Mackall
Add ui.progress API
r9153 and total is the highest expected pos.
Augie Fackler
ui.progress: clarify termination requirement
r10425 Multiple nested topics may be active at a time.
All topics should be marked closed by setting pos to None at
termination.
Matt Mackall
Add ui.progress API
r9153 '''
if pos == None or not self.debugflag:
return
Brodie Rao
ui: fix NameError in ui.progress due to unit/units typo
r9398 if unit:
unit = ' ' + unit
Matt Mackall
Add ui.progress API
r9153 if item:
item = ' ' + item
if total:
pct = 100.0 * pos / total
Patrick Mezard
ui: display progress with decimal notation
r10220 self.debug('%s:%s %s/%s%s (%4.2f%%)\n'
Brodie Rao
ui: fix NameError in ui.progress due to unit/units typo
r9398 % (topic, item, pos, total, unit, pct))
Matt Mackall
Add ui.progress API
r9153 else:
Jesse Glick
Related to Issue919: ui.progress, apparently unused before now, is busted.
r9749 self.debug('%s:%s %s%s\n' % (topic, item, pos, unit))
Brodie Rao
ui: add ui.write() output labeling API...
r10815
Matt Mackall
ui: add logging hook
r11984 def log(self, service, message):
'''hook for logging facility extensions
service should be a readily-identifiable subsystem, which will
allow filtering.
message should be a newline-terminated string to log.
'''
pass
Brodie Rao
ui: add ui.write() output labeling API...
r10815 def label(self, msg, label):
'''style msg based on supplied label
Like ui.write(), this just returns msg unchanged, but extensions
and GUI tools can override it to allow styling output without
writing it.
ui.write(s, 'label') is equivalent to
ui.write(ui.label(s, 'label')).
'''
return msg