mercurial/config.py
changeset 31481 a7c687c35119
parent 31374 d30fb3de4b40
child 32318 6a773d3050c9
equal deleted inserted replaced
31480:07fe520280d2 31481:a7c687c35119
   177         assert getattr(fp, 'mode', r'rb') == r'rb', (
   177         assert getattr(fp, 'mode', r'rb') == r'rb', (
   178             'config files must be opened in binary mode, got fp=%r mode=%r' % (
   178             'config files must be opened in binary mode, got fp=%r mode=%r' % (
   179                 fp, fp.mode))
   179                 fp, fp.mode))
   180         self.parse(path, fp.read(),
   180         self.parse(path, fp.read(),
   181                    sections=sections, remap=remap, include=self.read)
   181                    sections=sections, remap=remap, include=self.read)
       
   182 
       
   183 def parselist(value):
       
   184     """parse a configuration value as a list of comma/space separated strings
       
   185 
       
   186     >>> parselist('this,is "a small" ,test')
       
   187     ['this', 'is', 'a small', 'test']
       
   188     """
       
   189 
       
   190     def _parse_plain(parts, s, offset):
       
   191         whitespace = False
       
   192         while offset < len(s) and (s[offset:offset + 1].isspace()
       
   193                                    or s[offset:offset + 1] == ','):
       
   194             whitespace = True
       
   195             offset += 1
       
   196         if offset >= len(s):
       
   197             return None, parts, offset
       
   198         if whitespace:
       
   199             parts.append('')
       
   200         if s[offset:offset + 1] == '"' and not parts[-1]:
       
   201             return _parse_quote, parts, offset + 1
       
   202         elif s[offset:offset + 1] == '"' and parts[-1][-1] == '\\':
       
   203             parts[-1] = parts[-1][:-1] + s[offset:offset + 1]
       
   204             return _parse_plain, parts, offset + 1
       
   205         parts[-1] += s[offset:offset + 1]
       
   206         return _parse_plain, parts, offset + 1
       
   207 
       
   208     def _parse_quote(parts, s, offset):
       
   209         if offset < len(s) and s[offset:offset + 1] == '"': # ""
       
   210             parts.append('')
       
   211             offset += 1
       
   212             while offset < len(s) and (s[offset:offset + 1].isspace() or
       
   213                     s[offset:offset + 1] == ','):
       
   214                 offset += 1
       
   215             return _parse_plain, parts, offset
       
   216 
       
   217         while offset < len(s) and s[offset:offset + 1] != '"':
       
   218             if (s[offset:offset + 1] == '\\' and offset + 1 < len(s)
       
   219                     and s[offset + 1:offset + 2] == '"'):
       
   220                 offset += 1
       
   221                 parts[-1] += '"'
       
   222             else:
       
   223                 parts[-1] += s[offset:offset + 1]
       
   224             offset += 1
       
   225 
       
   226         if offset >= len(s):
       
   227             real_parts = _configlist(parts[-1])
       
   228             if not real_parts:
       
   229                 parts[-1] = '"'
       
   230             else:
       
   231                 real_parts[0] = '"' + real_parts[0]
       
   232                 parts = parts[:-1]
       
   233                 parts.extend(real_parts)
       
   234             return None, parts, offset
       
   235 
       
   236         offset += 1
       
   237         while offset < len(s) and s[offset:offset + 1] in [' ', ',']:
       
   238             offset += 1
       
   239 
       
   240         if offset < len(s):
       
   241             if offset + 1 == len(s) and s[offset:offset + 1] == '"':
       
   242                 parts[-1] += '"'
       
   243                 offset += 1
       
   244             else:
       
   245                 parts.append('')
       
   246         else:
       
   247             return None, parts, offset
       
   248 
       
   249         return _parse_plain, parts, offset
       
   250 
       
   251     def _configlist(s):
       
   252         s = s.rstrip(' ,')
       
   253         if not s:
       
   254             return []
       
   255         parser, parts, offset = _parse_plain, [''], 0
       
   256         while parser:
       
   257             parser, parts, offset = parser(parts, s, offset)
       
   258         return parts
       
   259 
       
   260     if value is not None and isinstance(value, bytes):
       
   261         result = _configlist(value.lstrip(' ,\n'))
       
   262     else:
       
   263         result = value
       
   264     return result or []