\n'
- text += ''
+ text = ''
+ if d.id is not None:
+ text += f'\n'
+ text += ''
- text += ''
- if d.template_params is not None:
- text += 'template <'
- text += ', '.join([render_param(p) for p in d.template_params])
- text += '>\n'
- text += '
'
+ text += ''
+ if d.template_params is not None:
+ text += 'template <'
+ text += ', '.join([render_param(p) for p in d.template_params])
+ text += '>\n'
+ text += '
'
- text += ''
- end = ';'
- if d.kind == 'function' or d.kind == 'variable':
- text += d.type + ' ' if len(d.type) > 0 else ''
- elif d.kind == 'typedef':
- text += 'using '
- elif d.kind == 'define':
- end = ''
- else:
- text += d.kind + ' '
- text += d.name
+ text += '
'
+ end = ';'
+ if d.kind == 'function' or d.kind == 'variable':
+ text += d.type + ' ' if len(d.type) > 0 else ''
+ elif d.kind == 'typedef':
+ text += 'using '
+ elif d.kind == 'define':
+ end = ''
+ else:
+ text += d.kind + ' '
+ text += d.name
- if d.params is not None:
- params = ', '.join([
- (p.type + ' ' if p.type else '') + p.name for p in d.params])
- text += '(' + escape_html(params) + ')'
- if d.trailing_return_type:
- text += ' -⁠> ' + escape_html(d.trailing_return_type)
- elif d.kind == 'typedef':
- text += ' = ' + escape_html(d.type)
+ if d.params is not None:
+ params = ', '.join([
+ (p.type + ' ' if p.type else '') + p.name for p in d.params])
+ text += '(' + escape_html(params) + ')'
+ if d.trailing_return_type:
+ text += ' -⁠> ' + escape_html(d.trailing_return_type)
+ elif d.kind == 'typedef':
+ text += ' = ' + escape_html(d.type)
- text += end
- text += '
'
- text += '\n'
- if d.id is not None:
- text += f'\n'
- return text
+ text += end
+ text += '
'
+ text += '
\n'
+ if d.id is not None:
+ text += f'\n'
+ return text
class CxxHandler(BaseHandler):
- def __init__(self, **kwargs: Any) -> None:
- super().__init__(handler='cxx', **kwargs)
+ def __init__(self, **kwargs: Any) -> None:
+ super().__init__(handler='cxx', **kwargs)
- headers = [
- 'args.h', 'base.h', 'chrono.h', 'color.h', 'compile.h', 'format.h',
- 'os.h', 'ostream.h', 'printf.h', 'ranges.h', 'std.h', 'xchar.h'
- ]
+ headers = [
+ 'args.h', 'base.h', 'chrono.h', 'color.h', 'compile.h', 'format.h',
+ 'os.h', 'ostream.h', 'printf.h', 'ranges.h', 'std.h', 'xchar.h'
+ ]
- # Run doxygen.
- cmd = ['doxygen', '-']
- support_dir = Path(__file__).parents[3]
- top_dir = os.path.dirname(support_dir)
- include_dir = os.path.join(top_dir, 'include', 'fmt')
- self._ns2doxyxml = {}
- build_dir = os.path.join(top_dir, 'build')
- os.makedirs(build_dir, exist_ok=True)
- self._doxyxml_dir = os.path.join(build_dir, 'doxyxml')
- p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
- _, _ = p.communicate(input=r'''
- PROJECT_NAME = fmt
- GENERATE_XML = YES
- GENERATE_LATEX = NO
- GENERATE_HTML = NO
- INPUT = {0}
- XML_OUTPUT = {1}
- QUIET = YES
- AUTOLINK_SUPPORT = NO
- MACRO_EXPANSION = YES
- PREDEFINED = _WIN32=1 \
- __linux__=1 \
- FMT_ENABLE_IF(...)= \
- FMT_USE_USER_DEFINED_LITERALS=1 \
- FMT_USE_ALIAS_TEMPLATES=1 \
- FMT_USE_NONTYPE_TEMPLATE_ARGS=1 \
- FMT_API= \
- "FMT_BEGIN_NAMESPACE=namespace fmt {{" \
- "FMT_END_NAMESPACE=}}" \
- "FMT_DOC=1"
- '''.format(
- ' '.join([os.path.join(include_dir, h) for h in headers]),
- self._doxyxml_dir).encode('utf-8'))
- if p.returncode != 0:
- raise CalledProcessError(p.returncode, cmd)
+ # Run doxygen.
+ cmd = ['doxygen', '-']
+ support_dir = Path(__file__).parents[3]
+ top_dir = os.path.dirname(support_dir)
+ include_dir = os.path.join(top_dir, 'include', 'fmt')
+ self._ns2doxyxml = {}
+ build_dir = os.path.join(top_dir, 'build')
+ os.makedirs(build_dir, exist_ok=True)
+ self._doxyxml_dir = os.path.join(build_dir, 'doxyxml')
+ p = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
+ _, _ = p.communicate(input=r'''
+ PROJECT_NAME = fmt
+ GENERATE_XML = YES
+ GENERATE_LATEX = NO
+ GENERATE_HTML = NO
+ INPUT = {0}
+ XML_OUTPUT = {1}
+ QUIET = YES
+ AUTOLINK_SUPPORT = NO
+ MACRO_EXPANSION = YES
+ PREDEFINED = _WIN32=1 \
+ __linux__=1 \
+ FMT_ENABLE_IF(...)= \
+ FMT_USE_USER_DEFINED_LITERALS=1 \
+ FMT_USE_ALIAS_TEMPLATES=1 \
+ FMT_USE_NONTYPE_TEMPLATE_ARGS=1 \
+ FMT_API= \
+ "FMT_BEGIN_NAMESPACE=namespace fmt {{" \
+ "FMT_END_NAMESPACE=}}" \
+ "FMT_DOC=1"
+ '''.format(
+ ' '.join([os.path.join(include_dir, h) for h in headers]),
+ self._doxyxml_dir).encode('utf-8'))
+ if p.returncode != 0:
+ raise CalledProcessError(p.returncode, cmd)
- # Merge all file-level XMLs into one to simplify search.
- self._file_doxyxml = None
- for h in headers:
- filename = h.replace(".h", "_8h.xml")
- with open(os.path.join(self._doxyxml_dir, filename)) as f:
- doxyxml = ElementTree.parse(f)
- if self._file_doxyxml is None:
- self._file_doxyxml = doxyxml
- continue
- root = self._file_doxyxml.getroot()
- for node in doxyxml.getroot():
- root.append(node)
+ # Merge all file-level XMLs into one to simplify search.
+ self._file_doxyxml = None
+ for h in headers:
+ filename = h.replace(".h", "_8h.xml")
+ with open(os.path.join(self._doxyxml_dir, filename)) as f:
+ doxyxml = ElementTree.parse(f)
+ if self._file_doxyxml is None:
+ self._file_doxyxml = doxyxml
+ continue
+ root = self._file_doxyxml.getroot()
+ for node in doxyxml.getroot():
+ root.append(node)
- def collect_compound(self, identifier: str,
- cls: List[ElementTree.Element]) -> Definition:
- """Collect a compound definition such as a struct."""
- path = os.path.join(self._doxyxml_dir, cls[0].get('refid') + '.xml')
- with open(path) as f:
- xml = ElementTree.parse(f)
- node = xml.find('compounddef')
- d = Definition(identifier, node=node)
- d.template_params = convert_template_params(node)
- d.desc = get_description(node)
- d.members = []
- for m in \
- node.findall('sectiondef[@kind="public-attrib"]/memberdef') + \
- node.findall('sectiondef[@kind="public-func"]/memberdef'):
- name = m.find('name').text
- # Doxygen incorrectly classifies members of private unnamed unions as
- # public members of the containing class.
- if name.endswith('_'):
- continue
- desc = get_description(m)
- if len(desc) == 0:
- continue
- kind = m.get('kind')
- member = Definition(name if name else '', kind=kind, is_member=True)
- type_text = m.find('type').text
- member.type = type_text if type_text else ''
- if kind == 'function':
- member.params = convert_params(m)
- convert_return_type(member, m)
- member.template_params = None
- member.desc = desc
- d.members.append(member)
- return d
+ def collect_compound(self, identifier: str,
+ cls: List[ElementTree.Element]) -> Definition:
+ """Collect a compound definition such as a struct."""
+ path = os.path.join(self._doxyxml_dir, cls[0].get('refid') + '.xml')
+ with open(path) as f:
+ xml = ElementTree.parse(f)
+ node = xml.find('compounddef')
+ d = Definition(identifier, node=node)
+ d.template_params = convert_template_params(node)
+ d.desc = get_description(node)
+ d.members = []
+ for m in \
+ node.findall('sectiondef[@kind="public-attrib"]/memberdef') + \
+ node.findall('sectiondef[@kind="public-func"]/memberdef'):
+ name = m.find('name').text
+ # Doxygen incorrectly classifies members of private unnamed unions as
+ # public members of the containing class.
+ if name.endswith('_'):
+ continue
+ desc = get_description(m)
+ if len(desc) == 0:
+ continue
+ kind = m.get('kind')
+ member = Definition(name if name else '', kind=kind, is_member=True)
+ type_text = m.find('type').text
+ member.type = type_text if type_text else ''
+ if kind == 'function':
+ member.params = convert_params(m)
+ convert_return_type(member, m)
+ member.template_params = None
+ member.desc = desc
+ d.members.append(member)
+ return d
- def collect(self, identifier: str, _config: Mapping[str, Any]) -> Definition:
- qual_name = 'fmt::' + identifier
+ def collect(self, identifier: str, _config: Mapping[str, Any]) -> Definition:
+ qual_name = 'fmt::' + identifier
- param_str = None
- paren = qual_name.find('(')
- if paren > 0:
- qual_name, param_str = qual_name[:paren], qual_name[paren + 1:-1]
+ param_str = None
+ paren = qual_name.find('(')
+ if paren > 0:
+ qual_name, param_str = qual_name[:paren], qual_name[paren + 1:-1]
- colons = qual_name.rfind('::')
- namespace, name = qual_name[:colons], qual_name[colons + 2:]
+ colons = qual_name.rfind('::')
+ namespace, name = qual_name[:colons], qual_name[colons + 2:]
- # Load XML.
- doxyxml = self._ns2doxyxml.get(namespace)
- if doxyxml is None:
- path = f'namespace{namespace.replace("::", "_1_1")}.xml'
- with open(os.path.join(self._doxyxml_dir, path)) as f:
- doxyxml = ElementTree.parse(f)
- self._ns2doxyxml[namespace] = doxyxml
+ # Load XML.
+ doxyxml = self._ns2doxyxml.get(namespace)
+ if doxyxml is None:
+ path = f'namespace{namespace.replace("::", "_1_1")}.xml'
+ with open(os.path.join(self._doxyxml_dir, path)) as f:
+ doxyxml = ElementTree.parse(f)
+ self._ns2doxyxml[namespace] = doxyxml
- nodes = doxyxml.findall(
- f"compounddef/sectiondef/memberdef/name[.='{name}']/..")
- if len(nodes) == 0:
- nodes = self._file_doxyxml.findall(
- f"compounddef/sectiondef/memberdef/name[.='{name}']/..")
- candidates = []
- for node in nodes:
- # Process a function or a typedef.
- params = None
- d = Definition(name, node=node)
- if d.kind == 'function':
- params = convert_params(node)
- node_param_str = ', '.join([p.type for p in params])
- if param_str and param_str != node_param_str:
- candidates.append(f'{name}({node_param_str})')
- continue
- elif d.kind == 'define':
- params = []
- for p in node.findall('param'):
- param = Definition(p.find('defname').text, kind='param')
- param.type = None
- params.append(param)
- d.type = convert_type(node.find('type'))
- d.template_params = convert_template_params(node)
- d.params = params
- convert_return_type(d, node)
- d.desc = get_description(node)
- return d
+ nodes = doxyxml.findall(
+ f"compounddef/sectiondef/memberdef/name[.='{name}']/..")
+ if len(nodes) == 0:
+ nodes = self._file_doxyxml.findall(
+ f"compounddef/sectiondef/memberdef/name[.='{name}']/..")
+ candidates = []
+ for node in nodes:
+ # Process a function or a typedef.
+ params = None
+ d = Definition(name, node=node)
+ if d.kind == 'function':
+ params = convert_params(node)
+ node_param_str = ', '.join([p.type for p in params])
+ if param_str and param_str != node_param_str:
+ candidates.append(f'{name}({node_param_str})')
+ continue
+ elif d.kind == 'define':
+ params = []
+ for p in node.findall('param'):
+ param = Definition(p.find('defname').text, kind='param')
+ param.type = None
+ params.append(param)
+ d.type = convert_type(node.find('type'))
+ d.template_params = convert_template_params(node)
+ d.params = params
+ convert_return_type(d, node)
+ d.desc = get_description(node)
+ return d
- cls = doxyxml.findall(f"compounddef/innerclass[.='{qual_name}']")
- if not cls:
- raise Exception(f'Cannot find {identifier}. Candidates: {candidates}')
- return self.collect_compound(identifier, cls)
+ cls = doxyxml.findall(f"compounddef/innerclass[.='{qual_name}']")
+ if not cls:
+ raise Exception(f'Cannot find {identifier}. Candidates: {candidates}')
+ return self.collect_compound(identifier, cls)
- def render(self, d: Definition, config: dict) -> str:
- if d.id is not None:
- self.do_heading('', 0, id=d.id)
- text = '\n'
- text += render_decl(d)
- text += '
\n'
- text += doxyxml2html(d.desc)
- if d.members is not None:
- for m in d.members:
- text += self.render(m, config)
- text += '
\n'
- text += '
\n'
- return text
+ def render(self, d: Definition, config: dict) -> str:
+ if d.id is not None:
+ self.do_heading('', 0, id=d.id)
+ text = '\n'
+ text += render_decl(d)
+ text += '
\n'
+ text += doxyxml2html(d.desc)
+ if d.members is not None:
+ for m in d.members:
+ text += self.render(m, config)
+ text += '
\n'
+ text += '
\n'
+ return text
def get_handler(theme: str, custom_templates: Optional[str] = None,
**_config: Any) -> CxxHandler:
- """Return an instance of `CxxHandler`.
+ """Return an instance of `CxxHandler`.
- Arguments:
- theme: The theme to use when rendering contents.
- custom_templates: Directory containing custom templates.
- **_config: Configuration passed to the handler.
- """
- return CxxHandler(theme=theme, custom_templates=custom_templates)
+ Arguments:
+ theme: The theme to use when rendering contents.
+ custom_templates: Directory containing custom templates.
+ **_config: Configuration passed to the handler.
+ """
+ return CxxHandler(theme=theme, custom_templates=custom_templates)