##// END OF EJS Templates
Improved ui.edit():...
Thomas Arendsen Hein -
r1984:df7436f4 default
parent child Browse files
Show More
@@ -1,217 +1,219 b''
1 # ui.py - user interface bits for mercurial
1 # ui.py - user interface bits for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import ConfigParser
8 import ConfigParser
9 from i18n import gettext as _
9 from i18n import gettext as _
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "os re socket sys util")
11 demandload(globals(), "os re socket sys util tempfile")
12
12
13 class ui(object):
13 class ui(object):
14 def __init__(self, verbose=False, debug=False, quiet=False,
14 def __init__(self, verbose=False, debug=False, quiet=False,
15 interactive=True, parentui=None):
15 interactive=True, parentui=None):
16 self.overlay = {}
16 self.overlay = {}
17 if parentui is None:
17 if parentui is None:
18 # this is the parent of all ui children
18 # this is the parent of all ui children
19 self.parentui = None
19 self.parentui = None
20 self.cdata = ConfigParser.SafeConfigParser()
20 self.cdata = ConfigParser.SafeConfigParser()
21 self.readconfig(util.rcpath())
21 self.readconfig(util.rcpath())
22
22
23 self.quiet = self.configbool("ui", "quiet")
23 self.quiet = self.configbool("ui", "quiet")
24 self.verbose = self.configbool("ui", "verbose")
24 self.verbose = self.configbool("ui", "verbose")
25 self.debugflag = self.configbool("ui", "debug")
25 self.debugflag = self.configbool("ui", "debug")
26 self.interactive = self.configbool("ui", "interactive", True)
26 self.interactive = self.configbool("ui", "interactive", True)
27
27
28 self.updateopts(verbose, debug, quiet, interactive)
28 self.updateopts(verbose, debug, quiet, interactive)
29 self.diffcache = None
29 self.diffcache = None
30 else:
30 else:
31 # parentui may point to an ui object which is already a child
31 # parentui may point to an ui object which is already a child
32 self.parentui = parentui.parentui or parentui
32 self.parentui = parentui.parentui or parentui
33 parent_cdata = self.parentui.cdata
33 parent_cdata = self.parentui.cdata
34 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
34 self.cdata = ConfigParser.SafeConfigParser(parent_cdata.defaults())
35 # make interpolation work
35 # make interpolation work
36 for section in parent_cdata.sections():
36 for section in parent_cdata.sections():
37 self.cdata.add_section(section)
37 self.cdata.add_section(section)
38 for name, value in parent_cdata.items(section, raw=True):
38 for name, value in parent_cdata.items(section, raw=True):
39 self.cdata.set(section, name, value)
39 self.cdata.set(section, name, value)
40
40
41 def __getattr__(self, key):
41 def __getattr__(self, key):
42 return getattr(self.parentui, key)
42 return getattr(self.parentui, key)
43
43
44 def updateopts(self, verbose=False, debug=False, quiet=False,
44 def updateopts(self, verbose=False, debug=False, quiet=False,
45 interactive=True):
45 interactive=True):
46 self.quiet = (self.quiet or quiet) and not verbose and not debug
46 self.quiet = (self.quiet or quiet) and not verbose and not debug
47 self.verbose = (self.verbose or verbose) or debug
47 self.verbose = (self.verbose or verbose) or debug
48 self.debugflag = (self.debugflag or debug)
48 self.debugflag = (self.debugflag or debug)
49 self.interactive = (self.interactive and interactive)
49 self.interactive = (self.interactive and interactive)
50
50
51 def readconfig(self, fn, root=None):
51 def readconfig(self, fn, root=None):
52 if isinstance(fn, basestring):
52 if isinstance(fn, basestring):
53 fn = [fn]
53 fn = [fn]
54 for f in fn:
54 for f in fn:
55 try:
55 try:
56 self.cdata.read(f)
56 self.cdata.read(f)
57 except ConfigParser.ParsingError, inst:
57 except ConfigParser.ParsingError, inst:
58 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
58 raise util.Abort(_("Failed to parse %s\n%s") % (f, inst))
59 # translate paths relative to root (or home) into absolute paths
59 # translate paths relative to root (or home) into absolute paths
60 if root is None:
60 if root is None:
61 root = os.path.expanduser('~')
61 root = os.path.expanduser('~')
62 for name, path in self.configitems("paths"):
62 for name, path in self.configitems("paths"):
63 if path and path.find("://") == -1 and not os.path.isabs(path):
63 if path and path.find("://") == -1 and not os.path.isabs(path):
64 self.cdata.set("paths", name, os.path.join(root, path))
64 self.cdata.set("paths", name, os.path.join(root, path))
65
65
66 def setconfig(self, section, name, val):
66 def setconfig(self, section, name, val):
67 self.overlay[(section, name)] = val
67 self.overlay[(section, name)] = val
68
68
69 def config(self, section, name, default=None):
69 def config(self, section, name, default=None):
70 if self.overlay.has_key((section, name)):
70 if self.overlay.has_key((section, name)):
71 return self.overlay[(section, name)]
71 return self.overlay[(section, name)]
72 if self.cdata.has_option(section, name):
72 if self.cdata.has_option(section, name):
73 try:
73 try:
74 return self.cdata.get(section, name)
74 return self.cdata.get(section, name)
75 except ConfigParser.InterpolationError, inst:
75 except ConfigParser.InterpolationError, inst:
76 raise util.Abort(_("Error in configuration:\n%s") % inst)
76 raise util.Abort(_("Error in configuration:\n%s") % inst)
77 if self.parentui is None:
77 if self.parentui is None:
78 return default
78 return default
79 else:
79 else:
80 return self.parentui.config(section, name, default)
80 return self.parentui.config(section, name, default)
81
81
82 def configbool(self, section, name, default=False):
82 def configbool(self, section, name, default=False):
83 if self.overlay.has_key((section, name)):
83 if self.overlay.has_key((section, name)):
84 return self.overlay[(section, name)]
84 return self.overlay[(section, name)]
85 if self.cdata.has_option(section, name):
85 if self.cdata.has_option(section, name):
86 try:
86 try:
87 return self.cdata.getboolean(section, name)
87 return self.cdata.getboolean(section, name)
88 except ConfigParser.InterpolationError, inst:
88 except ConfigParser.InterpolationError, inst:
89 raise util.Abort(_("Error in configuration:\n%s") % inst)
89 raise util.Abort(_("Error in configuration:\n%s") % inst)
90 if self.parentui is None:
90 if self.parentui is None:
91 return default
91 return default
92 else:
92 else:
93 return self.parentui.configbool(section, name, default)
93 return self.parentui.configbool(section, name, default)
94
94
95 def configitems(self, section):
95 def configitems(self, section):
96 items = {}
96 items = {}
97 if self.parentui is not None:
97 if self.parentui is not None:
98 items = dict(self.parentui.configitems(section))
98 items = dict(self.parentui.configitems(section))
99 if self.cdata.has_section(section):
99 if self.cdata.has_section(section):
100 try:
100 try:
101 items.update(dict(self.cdata.items(section)))
101 items.update(dict(self.cdata.items(section)))
102 except ConfigParser.InterpolationError, inst:
102 except ConfigParser.InterpolationError, inst:
103 raise util.Abort(_("Error in configuration:\n%s") % inst)
103 raise util.Abort(_("Error in configuration:\n%s") % inst)
104 x = items.items()
104 x = items.items()
105 x.sort()
105 x.sort()
106 return x
106 return x
107
107
108 def walkconfig(self, seen=None):
108 def walkconfig(self, seen=None):
109 if seen is None:
109 if seen is None:
110 seen = {}
110 seen = {}
111 for (section, name), value in self.overlay.iteritems():
111 for (section, name), value in self.overlay.iteritems():
112 yield section, name, value
112 yield section, name, value
113 seen[section, name] = 1
113 seen[section, name] = 1
114 for section in self.cdata.sections():
114 for section in self.cdata.sections():
115 for name, value in self.cdata.items(section):
115 for name, value in self.cdata.items(section):
116 if (section, name) in seen: continue
116 if (section, name) in seen: continue
117 yield section, name, value.replace('\n', '\\n')
117 yield section, name, value.replace('\n', '\\n')
118 seen[section, name] = 1
118 seen[section, name] = 1
119 if self.parentui is not None:
119 if self.parentui is not None:
120 for parent in self.parentui.walkconfig(seen):
120 for parent in self.parentui.walkconfig(seen):
121 yield parent
121 yield parent
122
122
123 def extensions(self):
123 def extensions(self):
124 return self.configitems("extensions")
124 return self.configitems("extensions")
125
125
126 def diffopts(self):
126 def diffopts(self):
127 if self.diffcache:
127 if self.diffcache:
128 return self.diffcache
128 return self.diffcache
129 ret = { 'showfunc' : True, 'ignorews' : False}
129 ret = { 'showfunc' : True, 'ignorews' : False}
130 for x in self.configitems("diff"):
130 for x in self.configitems("diff"):
131 k = x[0].lower()
131 k = x[0].lower()
132 v = x[1]
132 v = x[1]
133 if v:
133 if v:
134 v = v.lower()
134 v = v.lower()
135 if v == 'true':
135 if v == 'true':
136 value = True
136 value = True
137 else:
137 else:
138 value = False
138 value = False
139 ret[k] = value
139 ret[k] = value
140 self.diffcache = ret
140 self.diffcache = ret
141 return ret
141 return ret
142
142
143 def username(self):
143 def username(self):
144 return (os.environ.get("HGUSER") or
144 return (os.environ.get("HGUSER") or
145 self.config("ui", "username") or
145 self.config("ui", "username") or
146 os.environ.get("EMAIL") or
146 os.environ.get("EMAIL") or
147 (os.environ.get("LOGNAME",
147 (os.environ.get("LOGNAME",
148 os.environ.get("USERNAME", "unknown"))
148 os.environ.get("USERNAME", "unknown"))
149 + '@' + socket.getfqdn()))
149 + '@' + socket.getfqdn()))
150
150
151 def shortuser(self, user):
151 def shortuser(self, user):
152 """Return a short representation of a user name or email address."""
152 """Return a short representation of a user name or email address."""
153 if not self.verbose: user = util.shortuser(user)
153 if not self.verbose: user = util.shortuser(user)
154 return user
154 return user
155
155
156 def expandpath(self, loc):
156 def expandpath(self, loc):
157 """Return repository location relative to cwd or from [paths]"""
157 """Return repository location relative to cwd or from [paths]"""
158 if loc.find("://") != -1 or os.path.exists(loc):
158 if loc.find("://") != -1 or os.path.exists(loc):
159 return loc
159 return loc
160
160
161 return self.config("paths", loc, loc)
161 return self.config("paths", loc, loc)
162
162
163 def write(self, *args):
163 def write(self, *args):
164 for a in args:
164 for a in args:
165 sys.stdout.write(str(a))
165 sys.stdout.write(str(a))
166
166
167 def write_err(self, *args):
167 def write_err(self, *args):
168 if not sys.stdout.closed: sys.stdout.flush()
168 if not sys.stdout.closed: sys.stdout.flush()
169 for a in args:
169 for a in args:
170 sys.stderr.write(str(a))
170 sys.stderr.write(str(a))
171
171
172 def flush(self):
172 def flush(self):
173 try:
173 try:
174 sys.stdout.flush()
174 sys.stdout.flush()
175 finally:
175 finally:
176 sys.stderr.flush()
176 sys.stderr.flush()
177
177
178 def readline(self):
178 def readline(self):
179 return sys.stdin.readline()[:-1]
179 return sys.stdin.readline()[:-1]
180 def prompt(self, msg, pat, default="y"):
180 def prompt(self, msg, pat, default="y"):
181 if not self.interactive: return default
181 if not self.interactive: return default
182 while 1:
182 while 1:
183 self.write(msg, " ")
183 self.write(msg, " ")
184 r = self.readline()
184 r = self.readline()
185 if re.match(pat, r):
185 if re.match(pat, r):
186 return r
186 return r
187 else:
187 else:
188 self.write(_("unrecognized response\n"))
188 self.write(_("unrecognized response\n"))
189 def status(self, *msg):
189 def status(self, *msg):
190 if not self.quiet: self.write(*msg)
190 if not self.quiet: self.write(*msg)
191 def warn(self, *msg):
191 def warn(self, *msg):
192 self.write_err(*msg)
192 self.write_err(*msg)
193 def note(self, *msg):
193 def note(self, *msg):
194 if self.verbose: self.write(*msg)
194 if self.verbose: self.write(*msg)
195 def debug(self, *msg):
195 def debug(self, *msg):
196 if self.debugflag: self.write(*msg)
196 if self.debugflag: self.write(*msg)
197 def edit(self, text, user):
197 def edit(self, text, user):
198 import tempfile
198 (fd, name) = tempfile.mkstemp(prefix="hg-editor-", suffix=".txt")
199 (fd, name) = tempfile.mkstemp("hg")
199 try:
200 f = os.fdopen(fd, "w")
200 f = os.fdopen(fd, "w")
201 f.write(text)
201 f.write(text)
202 f.close()
202 f.close()
203
204 editor = (os.environ.get("HGEDITOR") or
205 self.config("ui", "editor") or
206 os.environ.get("EDITOR", "vi"))
203
207
204 editor = (os.environ.get("HGEDITOR") or
208 util.system("%s \"%s\"" % (editor, name),
205 self.config("ui", "editor") or
209 environ={'HGUSER': user},
206 os.environ.get("EDITOR", "vi"))
210 onerr=util.Abort, errprefix=_("edit failed"))
207
211
208 util.system("%s \"%s\"" % (editor, name),
212 f = open(name)
209 environ={'HGUSER': user},
213 t = f.read()
210 onerr=util.Abort, errprefix=_("edit failed"))
214 f.close()
211
215 t = re.sub("(?m)^HG:.*\n", "", t)
212 t = open(name).read()
216 finally:
213 t = re.sub("(?m)^HG:.*\n", "", t)
217 os.unlink(name)
214
215 os.unlink(name)
216
218
217 return t
219 return t
General Comments 0
You need to be logged in to leave comments. Login now