| 123 | | _wiki_modules = "|".join([k for k, v in modules.items() if v[2]]) |
| | 123 | # regexp fragments for Trac objects: |
| | 124 | _page_name = ("(^|(?<=[^A-Za-z]))" # start of string or positive lookbehind is not a letter |
| | 125 | "[A-Z]" # first letter must be a capitalized letter, |
| | 126 | "[a-z]+" # followed by some lower case |
| | 127 | "(?:[A-Z][a-z]*[a-z/])+" # ... followed by one or more wiki page 'component' |
| | 128 | "(?:#[A-Za-z0-9]+)?" # optional reference to a section anchor |
| | 129 | "(?=\Z|\s|[.,;:!?\)}\]])" # lookahed for something indicating the end of the name |
| | 130 | ) |
| | 131 | _ticket_id = "\d+" |
| | 132 | _changeset_id = "\d+" |
| | 133 | _report_id = "\d+" |
| | 134 | |
| | 135 | _wiki_ref_modules = "|".join([k for k, v in modules.items() if v[2]]) |
| | 136 | _module_args = "("(.*?)"|'(.*?)')|([^ ]*[^'~_\., \)])" |
| | 137 | |
| | 138 | # regexp fragments for InterTrac support: |
| | 139 | _project_name = "[a-zA-Z0-9-_]+" |
| | 140 | _project_key = "[a-zA-Z]{,3}" # allow at most 3 letters for a project shorthand |
| | 141 | # Note: the end of _project_key should be differentiable |
| | 142 | # from the start of _ticket_id and _changeset_id |
| | 143 | |
| 133 | | # InterTrac support: |
| 134 | | r"(?P<it_tickethref>!?#((?P<it_ticket>[a-zA-z]+)\d+))", |
| 135 | | r"(?P<it_changesethref>!?(\[(?P<it_changeset>[a-zA-z]+)\d+\]))", |
| 136 | | r"(?P<it_modulehref>!?((?P<it_modulename>%s):(?P<it_module>[a-zA-z]+):(?P<it_moduleargs>("(.*?)"|'(.*?)')|([^ ]*[^'~_\., \)]))))" % _wiki_modules, |
| 137 | | r"(?P<tickethref>!?#\d+)", |
| 138 | | r"(?P<changesethref>!?(\[\d+\]|\br\d+\b))", |
| 139 | | r"(?P<reporthref>!?\{\d+\})", |
| 140 | | r"(?P<modulehref>!?((?P<modulename>%s):(?P<moduleargs>("(.*?)"|'(.*?)')|([^ ]*[^'~_\., \)]))))" % _wiki_modules, |
| 141 | | r"(?P<wikihref>!?(^|(?<=[^A-Za-z]))[A-Z][a-z]+(?:[A-Z][a-z]*[a-z/])+(?:#[A-Za-z0-9]+)?(?=\Z|\s|[.,;:!?\)}\]]))", |
| 142 | | r"(?P<fancylink>!?\[(?P<fancyurl>([a-z]+:[^ ]+)) (?P<linkname>.*?)\])"] |
| | 153 | # Trac Objects links: |
| | 154 | r"(?P<wikihref>!?%s)" % _page_name, |
| | 155 | r"(?P<tickethref>!?(?:%s:)?#%s)" % (_project_name, _ticket_id), |
| | 156 | r"(?P<changesethref>!?(?:%s:)?\[%s\]|\br%s\b)" % (_project_name, _changeset_id, _changeset_id), |
| | 157 | r"(?P<reporthref>!?(?:%s:)?\{%s\})" % (_project_name, _report_id), |
| | 158 | # Shorthand InterTrac links: |
| | 159 | r"(?P<it_tickethref>!?#((?P<it_ticket>%s)%s))" % (_project_key, _ticket_id), |
| | 160 | r"(?P<it_changesethref>!?(\[(?P<it_changeset>%s)%s\]))" % (_project_key, _changeset_id), |
| | 161 | r"(?P<it_reporthref>!?(\{(?P<it_report>%s)%s\}))" % (_project_key, _report_id), |
| | 162 | # Generic links: |
| | 163 | r"(?P<modulehref>!?((?P<it_module>%s:)?(?P<modulename>%s):(?P<moduleargs>%s)))" \ |
| | 164 | % (_project_name, _wiki_ref_modules, _module_args), |
| | 165 | r"(?P<fancylink>!?\[(?P<it_fancy>%s:)?(?P<fancyurl>([a-z]+:[^ ]+)) (?P<linkname>.*?)\])" \ |
| | 166 | % (_project_name), |
| | 167 | ] |
| 212 | | # InterTrac support: |
| | 237 | # Trac Objects links: |
| | 238 | |
| | 239 | def _wikihref_formatter(self, match, fullmatch): |
| | 240 | return self._make_wiki_link(match, match) |
| | 241 | |
| | 242 | def _tickethref_formatter(self, match, fullmatch): |
| | 243 | sep = match.find(':') |
| | 244 | if sep == -1: # #id |
| | 245 | return self._make_ticket_link(match[1:], match) |
| | 246 | else: # project:#id |
| | 247 | intertrac = match[:sep] |
| | 248 | id = match[sep+2:] |
| | 249 | return self._intertrac_link(intertrac, 'ticket', id, '#'+id, match) |
| | 250 | |
| | 251 | def _changesethref_formatter(self, match, fullmatch): |
| | 252 | if match[0] == 'r': |
| | 253 | return self._make_changeset_link(match[1:], match) |
| | 254 | else: |
| | 255 | sep = match.find(':') |
| | 256 | if sep == -1: # [id] |
| | 257 | return self._make_changeset_link(match[1:-1], match) |
| | 258 | else: # project:[id] |
| | 259 | intertrac = match[:sep] |
| | 260 | id = match[sep+2:-1] |
| | 261 | return self._intertrac_link(intertrac, 'changeset', id, '[%s]'%id, match) |
| | 262 | |
| | 263 | def _reporthref_formatter(self, match, fullmatch): |
| | 264 | sep = match.find(':') |
| | 265 | if sep == -1: # {id} |
| | 266 | return self._make_report_link(match[1:-1], match) |
| | 267 | else: |
| | 268 | intertrac = match[:sep] |
| | 269 | id = match[sep+2:-1] |
| | 270 | return self._intertrac_link(intertrac, 'report', id, '{%s}'%id, match) |
| | 271 | |
| | 272 | # Shorthand InterTrac links: |
| | 273 | |
| 221 | | return self._make_intertrac_link(intertrac, 'changeset', id, '[%s]' % id) |
| 222 | | |
| 223 | | def _it_modulehref_formatter(self, match, fullmatch): |
| 224 | | it_modulename = fullmatch.group('it_modulename') |
| 225 | | it_module = fullmatch.group('it_module') |
| 226 | | it_moduleargs = fullmatch.group('it_moduleargs') |
| 227 | | return self._make_intertrac_link(it_module, it_modulename, it_moduleargs, |
| 228 | | '%s:%s:%s' % (it_modulename, it_module, it_moduleargs)) |
| 229 | | |
| 230 | | def _tickethref_formatter(self, match, fullmatch): |
| 231 | | return self._make_ticket_link(match[1:], match) |
| 232 | | |
| 233 | | def _changesethref_formatter(self, match, fullmatch): |
| 234 | | if match[0] == 'r': |
| 235 | | rev = match[1:] |
| 236 | | else: |
| 237 | | rev = match[1:-1] |
| 238 | | return self._make_changeset_link(rev, match) |
| 239 | | |
| 240 | | def _reporthref_formatter(self, match, fullmatch): |
| 241 | | return self._make_report_link(match[1:-1], match) |
| 242 | | |
| 243 | | def _modulehref_formatter(self, match, fullmatch): |
| 244 | | return self._make_module_link(match, match) |
| 245 | | |
| 246 | | def _wikihref_formatter(self, match, fullmatch): |
| 247 | | return self._make_wiki_link(match, match) |
| 248 | | |
| | 282 | return self._intertrac_link(intertrac, 'changeset', id, '[%s]'%id, match) |
| | 283 | |
| | 284 | def _it_reporthref_formatter(self, match, fullmatch): |
| | 285 | intertrac = fullmatch.group('it_report') |
| | 286 | id = match[1+len(intertrac):-1] |
| | 287 | return self._intertrac_link(intertrac, 'report', id, '{%s}'%id, match) |
| | 288 | |
| | 289 | # Generic links: |
| | 290 | |
| | 294 | def _modulehref_formatter(self, match, fullmatch): |
| | 295 | it_module = fullmatch.group('it_module') |
| | 296 | modulename = fullmatch.group('modulename') |
| | 297 | moduleargs = fullmatch.group('moduleargs') |
| | 298 | if it_module: |
| | 299 | return self._intertrac_link(it_module[:-1], modulename, moduleargs, |
| | 300 | '%s:%s' % (modulename, moduleargs), match) |
| | 301 | else: |
| | 302 | return self._make_module_link(match, match) |
| | 303 | |
| 258 | | def _make_intertrac_link(self, intertrac, module, id, display_id): |
| 259 | | href = self.env.get_config('intertrac', intertrac.upper() + '.trac') |
| | 317 | def _intertrac_link(self, intertrac, module, id, target, text): |
| | 318 | # first, check if it is a project key |
| | 319 | intertrac = self.env.get_config('intertrac', intertrac.upper() + '.key', intertrac) |
| | 320 | # check if the project name is the one of a sibling environment: |
| | 321 | if self.env.siblings.has_key(intertrac): |
| | 322 | intertrac_env = self.env.siblings[intertrac] |
| | 323 | intertrac_fmt = OneLinerFormatter(intertrac_env, intertrac_env.get_db_cnx(), 1) |
| | 324 | return re.sub(intertrac_fmt._compiled_rules, intertrac_fmt.replace, target).replace(target, text) |
| | 325 | # otherwise, rely on project names that were configured |
| | 326 | href = self.env.get_config('intertrac', intertrac.upper() + '.url') |