##// END OF EJS Templates
test-context: add test for performing a diff on a memctx...
test-context: add test for performing a diff on a memctx We now see the first result of all that refactoring of memctx: we can now diff against a memctx.

File last commit:

r21195:9336bc7d stable
r21837:61b333b9 default
Show More
ui.py
851 lines | 30.8 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 _
Bryan O'Sullivan
ui: use util.sizetoint in configbytes
r19195 import errno, getpass, os, socket, sys, tempfile, traceback
Matt Mackall
ui: add formatter method
r16135 import config, scmutil, util, error, formatter
Alexander Drozdov
ui: edit(): transplant: set HGREVISION environment variable for an editor...
r20606 from node import hex
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):
Pierre-Yves David
ui: pushbuffer can now also capture stderr...
r21132 # _buffers: used for temporary capture of output
Matt Mackall
ui: buffers -> _buffers
r8202 self._buffers = []
Pierre-Yves David
ui: pushbuffer can now also capture stderr...
r21132 # _bufferstates: Should the temporary capture includes stderr
self._bufferstates = []
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()
Idan Kamara
ui: add a variable to control whether hooks should be called...
r17048 self.callhooks = True
Matt Mackall
ui: refactor option setting...
r8136
Matt Mackall
ui: kill most users of parentui name and arg, replace with .copy()
r8190 if src:
Idan Kamara
ui: add I/O descriptors
r14612 self.fout = src.fout
self.ferr = src.ferr
self.fin = src.fin
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
Idan Kamara
ui: add a variable to control whether hooks should be called...
r17048 self.callhooks = src.callhooks
Matt Mackall
ui: simplify init, kill dupconfig
r8143 self.fixconfig()
else:
Idan Kamara
ui: add I/O descriptors
r14612 self.fout = sys.stdout
self.ferr = sys.stderr
self.fin = sys.stdin
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
Adrian Buehlmann
move rcpath from util to scmutil
r13984 for f in scmutil.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: add formatter method
r16135 def formatter(self, topic, opts):
return formatter.formatter(self, topic, opts)
Matt Mackall
ui: rename _is_trusted to _trusted...
r14859 def _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:
Martin Geisler
ui: lowercase "not trusting file" warning message
r16939 self.warn(_('not trusting file %s from untrusted '
Matt Mackall
ui: cleanup _is_trusted a bit
r8141 '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: rename _is_trusted to _trusted...
r14859 trusted = sections or trust or self._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
misc: adding missing file close() calls...
r15407 fp.close()
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
Martin Geisler
ui: lowercase ConfigError warning message
r16938 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]
"Yann E. MORIN"
ui: enable alias exception when reading config in plain mode...
r14373 for k, v in cfg.items('defaults'):
del cfg['defaults'][k]
# Don't remove aliases from the configuration if in the exceptionlist
if self.plain('alias'):
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
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
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 def fixconfig(self, root=None, section=None):
if section in (None, 'paths'):
# expand vars and ~
# translate paths relative to root (or home) into absolute paths
root = root or os.getcwd()
for c in self._tcfg, self._ucfg, self._ocfg:
for n, p in c.items('paths'):
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)
Brodie Rao
url: move URL parsing functions into util to improve startup time...
r14076 if not util.hasscheme(p) and not os.path.isabs(p):
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 p = os.path.normpath(os.path.join(root, p))
c.set("paths", n, p)
Alexis S. L. Carvalho
ui.py: normalize settings every time the configuration changes...
r3347
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 if section in (None, 'ui'):
# update ui options
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
Ry4an Brase
ui: always report untrusted hgrc files when debug enabled...
r13493 self._reportuntrusted = self.debugflag or self.configbool("ui",
"report_untrusted", True)
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 self.tracebackflag = self.configbool('ui', 'traceback', False)
Alexis S. L. Carvalho
update ui.quiet/verbose/debug/interactive every time the config changes...
r3350
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 if section in (None, 'trusted'):
# update trust information
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
Pierre-Yves David
config: have a way to backup and restore value in config...
r15919 def backupconfig(self, section, item):
return (self._ocfg.backup(section, item),
self._tcfg.backup(section, item),
self._ucfg.backup(section, item),)
def restoreconfig(self, data):
self._ocfg.restore(data[0])
self._tcfg.restore(data[1])
self._ucfg.restore(data[2])
Mads Kiilerich
config: give a useful hint of source for the most common command line settings...
r20788 def setconfig(self, section, name, value, source=''):
Mads Kiilerich
config: backout 77f1f206e135 - 743daa601445 removed the only use of overlay
r20787 for cfg in (self._ocfg, self._tcfg, self._ucfg):
Mads Kiilerich
config: give a useful hint of source for the most common command line settings...
r20788 cfg.set(section, name, value, source)
Nicolas Dumazet
ui: only fix config if the relevant section has changed...
r12764 self.fixconfig(section=section)
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: allow alternatives for config options
r15035 if isinstance(name, list):
alternates = name
else:
alternates = [name]
for n in alternates:
Augie Fackler
ui.config: fix bug in config alternatives from cc669e4fec95
r19536 value = self._data(untrusted).get(section, n, None)
Matt Mackall
ui: allow alternatives for config options
r15035 if value is not None:
name = n
break
else:
value = default
Matt Mackall
ui: report_untrusted fixes...
r8204 if self.debugflag and not untrusted and self._reportuntrusted:
Augie Fackler
ui.config: fix bug in config alternatives from cc669e4fec95
r19536 for n in alternates:
uvalue = self._ucfg.get(section, n)
if uvalue is not None and uvalue != value:
self.debug("ignoring untrusted configuration option "
"%s.%s = %s\n" % (section, n, 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
Matt Mackall
ui: add configpath helper
r13238 def configpath(self, section, name, default=None, untrusted=False):
Simon Heimberg
ui: config path relative to repo root
r14924 'get a path config item, expanded relative to repo root or config file'
Matt Mackall
ui: add configpath helper
r13238 v = self.config(section, name, default, untrusted)
Simon Heimberg
ui: providing no default value to configpath should not raise an Error
r14923 if v is None:
return None
Matt Mackall
ui: add configpath helper
r13238 if not os.path.isabs(v) or "://" not in v:
src = self.configsource(section, name, untrusted)
if ':' in src:
Simon Heimberg
ui: fix error, base can not be a list
r14922 base = os.path.dirname(src.rsplit(':')[0])
Matt Mackall
ui: add configpath helper
r13238 v = os.path.join(base, os.path.expanduser(v))
return v
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 def configbool(self, section, name, default=False, untrusted=False):
Sune Foldager
ui: add configint function and tests
r14171 """parse a configuration element as a boolean
>>> u = ui(); s = 'foo'
>>> u.setconfig(s, 'true', 'yes')
>>> u.configbool(s, 'true')
True
>>> u.setconfig(s, 'false', 'no')
>>> u.configbool(s, 'false')
False
>>> u.configbool(s, 'unknown')
False
>>> u.configbool(s, 'unknown', True)
True
>>> u.setconfig(s, 'invalid', 'somevalue')
>>> u.configbool(s, 'invalid')
Traceback (most recent call last):
...
ConfigError: foo.invalid is not a boolean ('somevalue')
"""
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:
Sune Foldager
ui: add configint function and tests
r14171 raise error.ConfigError(_("%s.%s is not a boolean ('%s')")
Matt Mackall
ui: introduce new config parser
r8144 % (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
Sune Foldager
ui: add configint function and tests
r14171 def configint(self, section, name, default=None, untrusted=False):
"""parse a configuration element as an integer
>>> u = ui(); s = 'foo'
>>> u.setconfig(s, 'int1', '42')
>>> u.configint(s, 'int1')
42
>>> u.setconfig(s, 'int2', '-42')
>>> u.configint(s, 'int2')
-42
>>> u.configint(s, 'unknown', 7)
7
>>> u.setconfig(s, 'invalid', 'somevalue')
>>> u.configint(s, 'invalid')
Traceback (most recent call last):
...
ConfigError: foo.invalid is not an integer ('somevalue')
"""
v = self.config(section, name, None, untrusted)
if v is None:
return default
try:
return int(v)
except ValueError:
raise error.ConfigError(_("%s.%s is not an integer ('%s')")
% (section, name, v))
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 def configbytes(self, section, name, default=0, untrusted=False):
"""parse a configuration element as a quantity in bytes
Units can be specified as b (bytes), k or kb (kilobytes), m or
mb (megabytes), g or gb (gigabytes).
>>> u = ui(); s = 'foo'
>>> u.setconfig(s, 'val1', '42')
>>> u.configbytes(s, 'val1')
42
>>> u.setconfig(s, 'val2', '42.5 kb')
>>> u.configbytes(s, 'val2')
43520
>>> u.configbytes(s, 'unknown', '7 MB')
7340032
>>> u.setconfig(s, 'invalid', 'somevalue')
>>> u.configbytes(s, 'invalid')
Traceback (most recent call last):
...
ConfigError: foo.invalid is not a byte quantity ('somevalue')
"""
Bryan O'Sullivan
ui: use util.sizetoint in configbytes
r19195 value = self.config(section, name)
if value is None:
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 if not isinstance(default, str):
return default
Bryan O'Sullivan
ui: use util.sizetoint in configbytes
r19195 value = default
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 try:
Bryan O'Sullivan
ui: use util.sizetoint in configbytes
r19195 return util.sizetoint(value)
except error.ParseError:
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065 raise error.ConfigError(_("%s.%s is not a byte quantity ('%s')")
Bryan O'Sullivan
ui: use util.sizetoint in configbytes
r19195 % (section, name, value))
Bryan O'Sullivan
ui: add a configbytes method, for space configuration...
r19065
Alexis S. L. Carvalho
save settings from untrusted config files in a separate configparser...
r3552 def configlist(self, section, name, default=None, untrusted=False):
Sune Foldager
ui: add configint function and tests
r14171 """parse a configuration element as a list of comma/space separated
strings
>>> u = ui(); s = 'foo'
>>> u.setconfig(s, 'list1', 'this,is "a small" ,test')
>>> u.configlist(s, 'list1')
['this', 'is', 'a small', 'test']
"""
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:
David Soria Parra
i18n: remove translation of debug messages
r14708 self.debug("ignoring untrusted configuration option "
"%s.%s = %s\n" % (section, k, v))
Matt Mackall
ui: introduce new config parser
r8144 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):
Martin Geisler
ui: yield unchanged values in walkconfig...
r13576 yield section, name, value
Bryan O'Sullivan
Add commands.debugconfig....
r1028
"Yann E. MORIN"
ui: test plain mode against exceptions...
r14372 def plain(self, feature=None):
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325 '''is plain mode active?
Brodie Rao
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT...
r13849 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 either the
`HGPLAIN' or `HGPLAINEXCEPT' environment variables.
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325
"Yann E. MORIN"
ui: test plain mode against exceptions...
r14372 The return value can either be
- False if HGPLAIN is not set, or feature is in HGPLAINEXCEPT
- True otherwise
Dan Villiom Podlaski Christiansen
ui: document the formatted(), interactive() & plain() functions.
r11325 '''
Brodie Rao
HGPLAIN: allow exceptions to plain mode, like i18n, via HGPLAINEXCEPT...
r13849 if 'HGPLAIN' not in os.environ and 'HGPLAINEXCEPT' not in os.environ:
return False
exceptions = os.environ.get('HGPLAINEXCEPT', '').strip().split(',')
"Yann E. MORIN"
ui: test plain mode against exceptions...
r14372 if feature and exceptions:
return feature not in exceptions
return True
Brodie Rao
ui: add HGPLAIN environment variable for easier scripting...
r10455
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())
Martin Geisler
ui: lowercase "no username" warning
r16940 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:
Matt Mackall
ui: suggest config --edit when no username is set
r20574 raise util.Abort(_('no username supplied'),
hint=_('use "hg config --edit" '
Matt Mackall
ui: fix extra space in username abort
r20580 'to set your username'))
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]"""
Brodie Rao
url: move URL parsing functions into util to improve startup time...
r14076 if util.hasscheme(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
Pierre-Yves David
ui: pushbuffer can now also capture stderr...
r21132 def pushbuffer(self, error=False):
"""install a buffer to capture standar output of the ui object
If error is True, the error output will be captured too."""
Matt Mackall
ui: buffers -> _buffers
r8202 self._buffers.append([])
Pierre-Yves David
ui: pushbuffer can now also capture stderr...
r21132 self._bufferstates.append(error)
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.
'''
Pierre-Yves David
ui: pushbuffer can now also capture stderr...
r21132 self._bufferstates.pop()
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:
Idan Kamara
ui: use I/O descriptors internally...
r14614 self.fout.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:
Pierre-Yves David
ui: pushbuffer can now also capture stderr...
r21132 if self._bufferstates and self._bufferstates[-1]:
return self.write(*args, **opts)
Idan Kamara
ui: use I/O descriptors internally...
r14614 if not getattr(self.fout, 'closed', False):
self.fout.flush()
Benoit Boissinot
ignore EPIPE in ui.err_write...
r1989 for a in args:
Idan Kamara
ui: use I/O descriptors internally...
r14614 self.ferr.write(str(a))
Patrick Mezard
Flush stderr after write....
r4023 # stderr may be buffered under win32 when redirected to files,
# including stdout.
Idan Kamara
ui: use I/O descriptors internally...
r14614 if not getattr(self.ferr, 'closed', False):
self.ferr.flush()
Benoit Boissinot
ignore EPIPE in ui.err_write...
r1989 except IOError, inst:
Kevin Bullock
ui: swallow EBADF on stderr...
r16367 if inst.errno not in (errno.EPIPE, errno.EIO, errno.EBADF):
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):
Idan Kamara
ui: use I/O descriptors internally...
r14614 try: self.fout.flush()
Brodie Rao
cleanup: replace more naked excepts with more specific ones
r16703 except (IOError, ValueError): pass
Idan Kamara
ui: use I/O descriptors internally...
r14614 try: self.ferr.flush()
Brodie Rao
cleanup: replace more naked excepts with more specific ones
r16703 except (IOError, ValueError): pass
Vadim Gelfer
make ui flush output. this makes error happen if printing to /dev/full....
r1837
Matt Mackall
ui: add _isatty method to easily disable cooked I/O
r16751 def _isatty(self, fh):
if self.configbool('ui', 'nontty', False):
return False
return util.isatty(fh)
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:
Idan Kamara
util: add helper function isatty(fd) to check for tty-ness
r14515 # some environments replace stdin without implementing isatty
# usually those are non-interactive
Matt Mackall
ui: add _isatty method to easily disable cooked I/O
r16751 return self._isatty(self.fin)
Ronny Pfannschmidt
make ui.interactive() return false in case stdin lacks isatty
r10077
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:
Idan Kamara
util: add helper function isatty(fd) to check for tty-ness
r14515 # some environments replace stdout without implementing isatty
# usually those are non-interactive
Matt Mackall
ui: add _isatty method to easily disable cooked I/O
r16751 return self._isatty(self.fout)
Dan Villiom Podlaski Christiansen
ui: add ui.formatted configuration variable and accessor function....
r11324
return i
Dirkjan Ochtman
Don't try to determine interactivity if ui() called with interactive=False....
r5337 def _readline(self, prompt=''):
Matt Mackall
ui: add _isatty method to easily disable cooked I/O
r16751 if self._isatty(self.fin):
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
Idan Kamara
ui: use I/O descriptors internally...
r14614
Idan Kamara
ui: call write() so the prompt string goes through subclassed implementation
r15000 # call write() so output goes through subclassed implementation
# e.g. color extension on Windows
self.write(prompt)
Martin Geisler
ui: also swap sys.stdout with self.fout in _readline...
r15062 # instead of trying to emulate raw_input, swap (self.fin,
# self.fout) with (sys.stdin, sys.stdout)
oldin = sys.stdin
oldout = sys.stdout
Idan Kamara
ui: call write() so the prompt string goes through subclassed implementation
r15000 sys.stdin = self.fin
Martin Geisler
ui: also swap sys.stdout with self.fout in _readline...
r15062 sys.stdout = self.fout
Idan Kamara
ui: pass ' ' to raw_input when prompting...
r15053 line = raw_input(' ')
Martin Geisler
ui: also swap sys.stdout with self.fout in _readline...
r15062 sys.stdin = oldin
sys.stdout = oldout
Idan Kamara
ui: use I/O descriptors internally...
r14614
Steve Borho
workaround for raw_input() on Windows...
r5613 # 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:
Idan Kamara
ui: pass ' ' to raw_input when prompting...
r15053 r = self._readline(self.label(msg, 'ui.prompt'))
Simon Heimberg
ui: extract choice from prompt...
r9048 if not r:
return default
return r
except EOFError:
raise util.Abort(_('response expected'))
FUJIWARA Katsunori
ui: add "extractchoices()" to share the logic to extract choices from prompt
r20265 @staticmethod
def extractchoices(prompt):
"""Extract prompt message and list of choices from specified prompt.
This returns tuple "(message, choices)", and "choices" is the
list of tuple "(response character, text without &)".
"""
parts = prompt.split('$$')
msg = parts[0].rstrip(' ')
choices = [p.strip(' ') for p in parts[1:]]
return (msg,
[(s[s.index('&') + 1].lower(), s.replace('&', '', 1))
for s in choices])
Matt Mackall
ui: merge prompt text components into a singe string...
r19226 def promptchoice(self, prompt, default=0):
"""Prompt user with a message, read response, and ensure it matches
one of the provided choices. The prompt is formatted as follows:
"would you like fries with that (Yn)? $$ &Yes $$ &No"
The index of the choice is returned. Responses are case
insensitive. If ui is not interactive, the default is
returned.
Simon Heimberg
ui: extract choice from prompt...
r9048 """
Matt Mackall
ui: merge prompt text components into a singe string...
r19226
FUJIWARA Katsunori
ui: add "extractchoices()" to share the logic to extract choices from prompt
r20265 msg, choices = self.extractchoices(prompt)
resps = [r for r, t 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:
Matt Mackall
ui: send password prompts to stderr again (issue4056)
r19880 self.write_err(self.label(prompt or _('password: '), 'ui.prompt'))
Yuya Nishihara
cmdserver: forcibly use L channel to read password input (issue3161)...
r21195 # disable getpass() only if explicitly specified. it's still valid
# to interact with tty even if fin is not a tty.
if self.configbool('ui', 'nontty'):
return self.fin.readline().rstrip('\n')
else:
return getpass.getpass('')
Steve Borho
catch CTRL-D at password prompt...
r7798 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)
Alexander Drozdov
ui: allow edit() to work with revision extras...
r20603 def edit(self, text, user, extra={}):
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()
Alexander Drozdov
ui: edit(): rebase, graft: set HGREVISION environment variable for an editor...
r20605 environ = {'HGUSER': user}
Alexander Drozdov
ui: edit(): transplant: set HGREVISION environment variable for an editor...
r20606 if 'transplant_source' in extra:
environ.update({'HGREVISION': hex(extra['transplant_source'])})
Alexander Drozdov
ui: edit(): rebase, graft: set HGREVISION environment variable for an editor...
r20605 for label in ('source', 'rebase_source'):
if label in extra:
environ.update({'HGREVISION': extra[label]})
break
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),
Alexander Drozdov
ui: edit(): rebase, graft: set HGREVISION environment variable for an editor...
r20605 environ=environ,
Idan Kamara
ui: use ui out descriptor when calling util.system
r14738 onerr=util.Abort, errprefix=_("edit failed"),
out=self.fout)
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
Matt Harbison
ui: add 'force' parameter to traceback() to override the current print setting...
r18966 def traceback(self, exc=None, force=False):
'''print exception traceback if traceback printing enabled or forced.
Vadim Gelfer
add ui.print_exc(), make all traceback printing central.
r2335 only to call in exception handler. returns true if traceback
printed.'''
Matt Harbison
ui: add 'force' parameter to traceback() to override the current print setting...
r18966 if self.tracebackflag or force:
Matt Harbison
ui: add support for fully printing chained exception stacks in ui.traceback()...
r18965 if exc is None:
exc = sys.exc_info()
cause = getattr(exc[1], 'cause', None)
if cause is not None:
causetb = traceback.format_tb(cause[2])
exctb = traceback.format_tb(exc[2])
exconly = traceback.format_exception_only(cause[0], cause[1])
# exclude frame where 'exc' was chained and rethrown from exctb
self.write_err('Traceback (most recent call last):\n',
''.join(exctb[:-1]),
''.join(causetb),
''.join(exconly))
else:
Brodie Rao
cleanup: eradicate long lines
r16683 traceback.print_exception(exc[0], exc[1], exc[2],
file=self.ferr)
Matt Harbison
ui: add 'force' parameter to traceback() to override the current print setting...
r18966 return self.tracebackflag or force
Osku Salerma
Use VISUAL in addition to EDITOR when choosing the editor to use.
r5660
def geteditor(self):
'''return editor to use'''
Steven Stallion
plan9: initial support for plan 9 from bell labs...
r16383 if sys.platform == 'plan9':
# vi is the MIPS instruction simulator on Plan 9. We
# instead default to E to plumb commit messages to
# avoid confusion.
editor = 'E'
else:
editor = 'vi'
Osku Salerma
Use VISUAL in addition to EDITOR when choosing the editor to use.
r5660 return (os.environ.get("HGEDITOR") or
self.config("ui", "editor") or
os.environ.get("VISUAL") or
Steven Stallion
plan9: initial support for plan 9 from bell labs...
r16383 os.environ.get("EDITOR", editor))
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
Mads Kiilerich
fix trivial spelling errors
r17424 non-numeric marker of the current position (i.e. the currently
in-process file), 'pos' is the current numeric position (i.e.
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 '''
Martin Geisler
code style: prefer 'is' and 'is not' tests with singletons
r13031 if pos is None or not self.debugflag:
Matt Mackall
Add ui.progress API
r9153 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
Durham Goode
blackbox: adds a blackbox extension...
r18669 def log(self, service, *msg, **opts):
Matt Mackall
ui: add logging hook
r11984 '''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