hgkw/keyword.py
changeset 854 3450d7f7d1a3
parent 849 f7b34429edb7
child 864 2cadbd48a31b
equal deleted inserted replaced
853:65ec857290ab 854:3450d7f7d1a3
   161         self.ui = ui
   161         self.ui = ui
   162         self.repo = repo
   162         self.repo = repo
   163         self.match = match.match(repo.root, '', [], inc, exc)
   163         self.match = match.match(repo.root, '', [], inc, exc)
   164         self.restrict = kwtools['hgcmd'] in restricted.split()
   164         self.restrict = kwtools['hgcmd'] in restricted.split()
   165         self.record = False
   165         self.record = False
   166         self.re_kw = None
       
   167         self.re_kwexp = None
       
   168 
   166 
   169         kwmaps = self.ui.configitems('keywordmaps')
   167         kwmaps = self.ui.configitems('keywordmaps')
   170         if kwmaps: # override default templates
   168         if kwmaps: # override default templates
   171             self.templates = dict((k, templater.parsestring(v, False))
   169             self.templates = dict((k, templater.parsestring(v, False))
   172                                   for k, v in kwmaps)
   170                                   for k, v in kwmaps)
   174             self.templates = _defaultkwmaps(self.ui)
   172             self.templates = _defaultkwmaps(self.ui)
   175         templatefilters.filters.update({'utcdate': utcdate,
   173         templatefilters.filters.update({'utcdate': utcdate,
   176                                         'svnisodate': svnisodate,
   174                                         'svnisodate': svnisodate,
   177                                         'svnutcdate': svnutcdate})
   175                                         'svnutcdate': svnutcdate})
   178 
   176 
       
   177     @util.propertycache
   179     def escape(self):
   178     def escape(self):
   180         '''Returns bar-separated list of keywords.'''
   179         '''Returns bar-separated and escaped keywords.'''
   181         return '|'.join(map(re.escape, self.templates.keys()))
   180         return '|'.join(map(re.escape, self.templates.keys()))
   182 
   181 
       
   182     @util.propertycache
   183     def rekw(self):
   183     def rekw(self):
   184         '''Compiles regex for unexpanded keywords on demand.'''
   184         '''Returns regex for unexpanded keywords.'''
   185         if self.re_kw is None:
   185         return re.compile(r'\$(%s)\$' % self.escape)
   186             self.re_kw = re.compile(r'\$(%s)\$' % self.escape())
   186 
   187         return self.re_kw
   187     @util.propertycache
   188 
       
   189     def rekwexp(self):
   188     def rekwexp(self):
   190         '''Compiles regex for expanded keywords on demand.'''
   189         '''Returns regex for expanded keywords.'''
   191         if self.re_kwexp is None:
   190         return re.compile(r'\$(%s): [^$\n\r]*? \$' % self.escape)
   192             self.re_kwexp = re.compile(r'\$(%s): [^$\n\r]*? \$' % self.escape())
       
   193         return self.re_kwexp
       
   194 
   191 
   195     def substitute(self, data, path, ctx, subfunc):
   192     def substitute(self, data, path, ctx, subfunc):
   196         '''Replaces keywords in data with expanded template.'''
   193         '''Replaces keywords in data with expanded template.'''
   197         def kwsub(mobj):
   194         def kwsub(mobj):
   198             kw = mobj.group(1)
   195             kw = mobj.group(1)
   211 
   208 
   212     def expand(self, path, node, data):
   209     def expand(self, path, node, data):
   213         '''Returns data with keywords expanded.'''
   210         '''Returns data with keywords expanded.'''
   214         if not self.restrict and self.match(path) and not util.binary(data):
   211         if not self.restrict and self.match(path) and not util.binary(data):
   215             ctx = self.linkctx(path, node)
   212             ctx = self.linkctx(path, node)
   216             return self.substitute(data, path, ctx, self.rekw().sub)
   213             return self.substitute(data, path, ctx, self.rekw.sub)
   217         return data
   214         return data
   218 
   215 
   219     def iskwfile(self, cand, ctx):
   216     def iskwfile(self, cand, ctx):
   220         '''Returns subset of candidates which are configured for keyword
   217         '''Returns subset of candidates which are configured for keyword
   221         expansion are not symbolic links.'''
   218         expansion are not symbolic links.'''
   229             return
   226             return
   230         kwcmd = self.restrict and lookup # kwexpand/kwshrink
   227         kwcmd = self.restrict and lookup # kwexpand/kwshrink
   231         if self.restrict or expand and lookup:
   228         if self.restrict or expand and lookup:
   232             mf = ctx.manifest()
   229             mf = ctx.manifest()
   233         lctx = ctx
   230         lctx = ctx
   234         re_kw = (self.restrict or rekw) and self.rekw() or self.rekwexp()
   231         re_kw = (self.restrict or rekw) and self.rekw or self.rekwexp
   235         msg = (expand and _('overwriting %s expanding keywords\n')
   232         msg = (expand and _('overwriting %s expanding keywords\n')
   236                or _('overwriting %s shrinking keywords\n'))
   233                or _('overwriting %s shrinking keywords\n'))
   237         for f in candidates:
   234         for f in candidates:
   238             if self.restrict:
   235             if self.restrict:
   239                 data = self.repo.file(f).read(mf[f])
   236                 data = self.repo.file(f).read(mf[f])
   258                     self.repo.dirstate.normallookup(f)
   255                     self.repo.dirstate.normallookup(f)
   259 
   256 
   260     def shrink(self, fname, text):
   257     def shrink(self, fname, text):
   261         '''Returns text with all keyword substitutions removed.'''
   258         '''Returns text with all keyword substitutions removed.'''
   262         if self.match(fname) and not util.binary(text):
   259         if self.match(fname) and not util.binary(text):
   263             return _shrinktext(text, self.rekwexp().sub)
   260             return _shrinktext(text, self.rekwexp.sub)
   264         return text
   261         return text
   265 
   262 
   266     def shrinklines(self, fname, lines):
   263     def shrinklines(self, fname, lines):
   267         '''Returns lines with keyword substitutions removed.'''
   264         '''Returns lines with keyword substitutions removed.'''
   268         if self.match(fname):
   265         if self.match(fname):
   269             text = ''.join(lines)
   266             text = ''.join(lines)
   270             if not util.binary(text):
   267             if not util.binary(text):
   271                 return _shrinktext(text, self.rekwexp().sub).splitlines(True)
   268                 return _shrinktext(text, self.rekwexp.sub).splitlines(True)
   272         return lines
   269         return lines
   273 
   270 
   274     def wread(self, fname, data):
   271     def wread(self, fname, data):
   275         '''If in restricted mode returns data read from wdir with
   272         '''If in restricted mode returns data read from wdir with
   276         keyword substitutions removed.'''
   273         keyword substitutions removed.'''