hgkw/keyword.py
changeset 848 3e57838f5434
parent 846 d565787a8a5d
child 849 f7b34429edb7
equal deleted inserted replaced
846:d565787a8a5d 848:3e57838f5434
   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
   166 
   168 
   167         kwmaps = self.ui.configitems('keywordmaps')
   169         kwmaps = self.ui.configitems('keywordmaps')
   168         if kwmaps: # override default templates
   170         if kwmaps: # override default templates
   169             self.templates = dict((k, templater.parsestring(v, False))
   171             self.templates = dict((k, templater.parsestring(v, False))
   170                                   for k, v in kwmaps)
   172                                   for k, v in kwmaps)
   171         else:
   173         else:
   172             self.templates = _defaultkwmaps(self.ui)
   174             self.templates = _defaultkwmaps(self.ui)
   173         escaped = '|'.join(map(re.escape, self.templates.keys()))
       
   174         self.re_kw = re.compile(r'\$(%s)\$' % escaped)
       
   175         self.re_kwexp = re.compile(r'\$(%s): [^$\n\r]*? \$' % escaped)
       
   176 
       
   177         templatefilters.filters.update({'utcdate': utcdate,
   175         templatefilters.filters.update({'utcdate': utcdate,
   178                                         'svnisodate': svnisodate,
   176                                         'svnisodate': svnisodate,
   179                                         'svnutcdate': svnutcdate})
   177                                         'svnutcdate': svnutcdate})
       
   178 
       
   179     def escape(self):
       
   180         '''Returns bar-separated list of keywords.'''
       
   181         return '|'.join(map(re.escape, self.templates.keys()))
       
   182 
       
   183     def rekw(self):
       
   184         '''Compiles regex for unexpanded keywords on demand.'''
       
   185         if self.re_kw is None:
       
   186             self.re_kw = re.compile(r'\$(%s)\$' % self.escape())
       
   187         return self.re_kw
       
   188 
       
   189     def rekwexp(self):
       
   190         '''Compiles regex for expanded keywords on demand.'''
       
   191         if self.re_kwexp is None:
       
   192             self.re_kwexp = re.compile(r'\$(%s): [^$\n\r]*? \$' % self.escape())
       
   193         return self.re_kwexp
   180 
   194 
   181     def substitute(self, data, path, ctx, subfunc):
   195     def substitute(self, data, path, ctx, subfunc):
   182         '''Replaces keywords in data with expanded template.'''
   196         '''Replaces keywords in data with expanded template.'''
   183         def kwsub(mobj):
   197         def kwsub(mobj):
   184             kw = mobj.group(1)
   198             kw = mobj.group(1)
   193 
   207 
   194     def expand(self, path, node, data):
   208     def expand(self, path, node, data):
   195         '''Returns data with keywords expanded.'''
   209         '''Returns data with keywords expanded.'''
   196         if not self.restrict and self.match(path) and not util.binary(data):
   210         if not self.restrict and self.match(path) and not util.binary(data):
   197             ctx = self.repo.filectx(path, fileid=node).changectx()
   211             ctx = self.repo.filectx(path, fileid=node).changectx()
   198             return self.substitute(data, path, ctx, self.re_kw.sub)
   212             return self.substitute(data, path, ctx, self.rekw().sub)
   199         return data
   213         return data
   200 
   214 
   201     def iskwfile(self, cand, ctx):
   215     def iskwfile(self, cand, ctx):
   202         '''Returns subset of candidates which are configured for keyword
   216         '''Returns subset of candidates which are configured for keyword
   203         expansion are not symbolic links.'''
   217         expansion are not symbolic links.'''
   211             return
   225             return
   212         kwcmd = self.restrict and lookup # kwexpand/kwshrink
   226         kwcmd = self.restrict and lookup # kwexpand/kwshrink
   213         if self.restrict or expand and lookup:
   227         if self.restrict or expand and lookup:
   214             mf = ctx.manifest()
   228             mf = ctx.manifest()
   215         fctx = ctx
   229         fctx = ctx
   216         subn = (self.restrict or rekw) and self.re_kw.subn or self.re_kwexp.subn
   230         re_kw = (self.restrict or rekw) and self.rekw() or self.rekwexp()
   217         msg = (expand and _('overwriting %s expanding keywords\n')
   231         msg = (expand and _('overwriting %s expanding keywords\n')
   218                or _('overwriting %s shrinking keywords\n'))
   232                or _('overwriting %s shrinking keywords\n'))
   219         for f in candidates:
   233         for f in candidates:
   220             if self.restrict:
   234             if self.restrict:
   221                 data = self.repo.file(f).read(mf[f])
   235                 data = self.repo.file(f).read(mf[f])
   224             if util.binary(data):
   238             if util.binary(data):
   225                 continue
   239                 continue
   226             if expand:
   240             if expand:
   227                 if lookup:
   241                 if lookup:
   228                     fctx = self.repo.filectx(f, fileid=mf[f]).changectx()
   242                     fctx = self.repo.filectx(f, fileid=mf[f]).changectx()
   229                 data, found = self.substitute(data, f, fctx, subn)
   243                 data, found = self.substitute(data, f, fctx, re_kw.subn)
   230             elif self.restrict:
   244             elif self.restrict:
   231                 found = self.re_kw.search(data)
   245                 found = re_kw.search(data)
   232             else:
   246             else:
   233                 data, found = _shrinktext(data, subn)
   247                 data, found = _shrinktext(data, re_kw.subn)
   234             if found:
   248             if found:
   235                 self.ui.note(msg % f)
   249                 self.ui.note(msg % f)
   236                 self.repo.wwrite(f, data, ctx.flags(f))
   250                 self.repo.wwrite(f, data, ctx.flags(f))
   237                 if kwcmd:
   251                 if kwcmd:
   238                     self.repo.dirstate.normal(f)
   252                     self.repo.dirstate.normal(f)
   240                     self.repo.dirstate.normallookup(f)
   254                     self.repo.dirstate.normallookup(f)
   241 
   255 
   242     def shrink(self, fname, text):
   256     def shrink(self, fname, text):
   243         '''Returns text with all keyword substitutions removed.'''
   257         '''Returns text with all keyword substitutions removed.'''
   244         if self.match(fname) and not util.binary(text):
   258         if self.match(fname) and not util.binary(text):
   245             return _shrinktext(text, self.re_kwexp.sub)
   259             return _shrinktext(text, self.rekwexp().sub)
   246         return text
   260         return text
   247 
   261 
   248     def shrinklines(self, fname, lines):
   262     def shrinklines(self, fname, lines):
   249         '''Returns lines with keyword substitutions removed.'''
   263         '''Returns lines with keyword substitutions removed.'''
   250         if self.match(fname):
   264         if self.match(fname):
   251             text = ''.join(lines)
   265             text = ''.join(lines)
   252             if not util.binary(text):
   266             if not util.binary(text):
   253                 return _shrinktext(text, self.re_kwexp.sub).splitlines(True)
   267                 return _shrinktext(text, self.rekwexp().sub).splitlines(True)
   254         return lines
   268         return lines
   255 
   269 
   256     def wread(self, fname, data):
   270     def wread(self, fname, data):
   257         '''If in restricted mode returns data read from wdir with
   271         '''If in restricted mode returns data read from wdir with
   258         keyword substitutions removed.'''
   272         keyword substitutions removed.'''