parent
99e531ec0e
commit
9c57255dec
|
@ -7,7 +7,7 @@ BUILDDIR = _build
|
|||
# Internal variables
|
||||
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||
PAPEROPT_letter = -D latex_paper_size=letter
|
||||
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
ALLSPHINXOPTS = -T -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
|
||||
|
||||
GH_PAGES_SOURCES = source Makefile
|
||||
GH_SOURCE_BRANCH = develop
|
||||
|
@ -32,3 +32,8 @@ html:
|
|||
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||
@echo
|
||||
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||
|
||||
man:
|
||||
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||
@echo
|
||||
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
:orphan:
|
||||
|
||||
powerline-config manual page
|
||||
============================
|
||||
|
||||
.. automan:: powerline.commands.config
|
||||
:prog: powerline-config
|
||||
|
||||
See also
|
||||
--------
|
||||
|
||||
:manpage:`powerline(1)`
|
|
@ -0,0 +1,12 @@
|
|||
:orphan:
|
||||
|
||||
powerline-daemon manual page
|
||||
============================
|
||||
|
||||
.. automan:: powerline.commands.daemon
|
||||
:prog: powerline-daemon
|
||||
|
||||
See also
|
||||
--------
|
||||
|
||||
:manpage:`powerline(1)`
|
|
@ -0,0 +1,12 @@
|
|||
:orphan:
|
||||
|
||||
powerline manual page
|
||||
=====================
|
||||
|
||||
.. automan:: powerline.commands.main
|
||||
:prog: powerline
|
||||
|
||||
See also
|
||||
--------
|
||||
|
||||
:manpage:`powerline-daemon(1)`, :manpage:`powerline-config(1)`
|
|
@ -8,7 +8,10 @@ import sys
|
|||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(os.getcwd()))))
|
||||
sys.path.insert(0, os.path.abspath(os.getcwd()))
|
||||
|
||||
extensions = ['powerline_autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode']
|
||||
extensions = [
|
||||
'powerline_autodoc', 'powerline_automan',
|
||||
'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.viewcode',
|
||||
]
|
||||
source_suffix = '.rst'
|
||||
master_doc = 'index'
|
||||
project = 'Powerline'
|
||||
|
@ -31,6 +34,22 @@ latex_elements = {
|
|||
''',
|
||||
}
|
||||
|
||||
man_pages = []
|
||||
for doc in os.listdir(os.path.join(os.path.dirname(__file__), 'commands')):
|
||||
if doc.endswith('.rst'):
|
||||
name = doc[:-4]
|
||||
module = 'powerline.commands.{0}'.format(name)
|
||||
get_argparser = __import__(str(module), fromlist=[str('get_argparser')]).get_argparser
|
||||
parser = get_argparser()
|
||||
description = parser.description
|
||||
man_pages.append([
|
||||
'commands/' + name,
|
||||
'powerline' if name == 'main' else 'powerline-' + name,
|
||||
description,
|
||||
'',
|
||||
1
|
||||
])
|
||||
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
|
||||
if not on_rtd: # only import and set the theme if we’re building docs locally
|
||||
|
|
|
@ -5,6 +5,14 @@ License and credits
|
|||
Powerline is licensed under the `MIT license
|
||||
<https://raw.github.com/Lokaltog/powerline/develop/LICENSE>`_.
|
||||
|
||||
..
|
||||
This document is parsed by powerline_automan.py module. Do not forget to
|
||||
check that file before altering this one. Specifically it expects
|
||||
``Authors`` and ``Contributors`` sections underlined by ``---``, a list of
|
||||
authors in format ``* `{name} <`` in the “Authors” section and fonts
|
||||
contributor name in format ``The glyphs in the font patcher are created by
|
||||
{name},`` in the “Contributors” section.
|
||||
|
||||
Authors
|
||||
-------
|
||||
|
||||
|
|
|
@ -0,0 +1,384 @@
|
|||
# vim:fileencoding=utf-8:noet
|
||||
from __future__ import (unicode_literals, division, absolute_import, print_function)
|
||||
|
||||
import os
|
||||
import re
|
||||
import codecs
|
||||
|
||||
from collections import namedtuple
|
||||
|
||||
from docutils.parsers.rst import Directive
|
||||
from docutils.parsers.rst.directives import unchanged_required
|
||||
from docutils import nodes
|
||||
|
||||
from powerline.lib.unicode import u
|
||||
|
||||
|
||||
AUTHOR_LINE_START = '* `'
|
||||
GLYPHS_AUTHOR_LINE_START = '* The glyphs in the font patcher are created by '
|
||||
|
||||
|
||||
def get_authors():
|
||||
credits_file = os.path.join(os.path.dirname(__file__), 'license-and-credits.rst')
|
||||
authors = []
|
||||
glyphs_author = None
|
||||
with codecs.open(credits_file, encoding='utf-8') as CF:
|
||||
section = None
|
||||
prev_line = None
|
||||
for line in CF:
|
||||
line = line[:-1]
|
||||
if line and not line.replace('-', ''):
|
||||
section = prev_line
|
||||
elif section == 'Authors':
|
||||
if line.startswith(AUTHOR_LINE_START):
|
||||
authors.append(line[len(AUTHOR_LINE_START):line.index('<')].strip())
|
||||
elif section == 'Contributors':
|
||||
if line.startswith(GLYPHS_AUTHOR_LINE_START):
|
||||
assert(not glyphs_author)
|
||||
glyphs_author = line[len(GLYPHS_AUTHOR_LINE_START):line.index(',')].strip()
|
||||
prev_line = line
|
||||
return {
|
||||
'authors': ', '.join(authors),
|
||||
'glyphs_author': glyphs_author,
|
||||
}
|
||||
|
||||
|
||||
class AutoManSubparsers(object):
|
||||
def __init__(self):
|
||||
self.parsers = []
|
||||
|
||||
def add_parser(self, command, *args, **kwargs):
|
||||
self.parsers.append((command, AutoManParser(*args, **kwargs)))
|
||||
return self.parsers[-1][1]
|
||||
|
||||
|
||||
Argument = namedtuple('Argument', ('names', 'help', 'choices', 'metavar', 'required', 'nargs', 'is_option', 'is_long_option', 'is_short_option', 'multi', 'can_be_joined'))
|
||||
|
||||
|
||||
def parse_argument(*args, **kwargs):
|
||||
is_option = args[0].startswith('-')
|
||||
is_long_option = args[0].startswith('--')
|
||||
is_short_option = is_option and not is_long_option
|
||||
action = kwargs.get('action', 'store_true')
|
||||
multi = kwargs.get('action') in ('append',)
|
||||
nargs = kwargs.get('nargs') or (1 if kwargs.get('metavar') or action in ('append',) else 0)
|
||||
return Argument(
|
||||
names=args,
|
||||
help=u(kwargs.get('help', '')),
|
||||
choices=[str(choice) for choice in kwargs.get('choices', [])],
|
||||
metavar=kwargs.get('metavar') or args[-1].lstrip('-').replace('-', '_').upper(),
|
||||
required=kwargs.get('required', False) if is_option else (
|
||||
kwargs.get('nargs') not in ('?',)),
|
||||
nargs=nargs,
|
||||
multi=multi,
|
||||
is_option=is_option,
|
||||
is_long_option=is_long_option,
|
||||
is_short_option=is_short_option,
|
||||
can_be_joined=(is_short_option and not multi and not nargs)
|
||||
)
|
||||
|
||||
|
||||
class AutoManGroup(object):
|
||||
is_short_option = False
|
||||
is_option = False
|
||||
is_long_option = False
|
||||
can_be_joined = False
|
||||
|
||||
def __init__(self):
|
||||
self.arguments = []
|
||||
self.required = False
|
||||
|
||||
def add_argument(self, *args, **kwargs):
|
||||
self.arguments.append(parse_argument(*args, **kwargs))
|
||||
|
||||
|
||||
class SurroundWith():
|
||||
def __init__(self, ret, condition, start='[', end=']'):
|
||||
self.ret = ret
|
||||
self.condition = condition
|
||||
self.start = start
|
||||
self.end = end
|
||||
|
||||
def __enter__(self, *args):
|
||||
if self.condition:
|
||||
self.ret.append(nodes.Text(self.start))
|
||||
|
||||
def __exit__(self, *args):
|
||||
if self.condition:
|
||||
self.ret.append(nodes.Text(self.end))
|
||||
|
||||
|
||||
def insert_separators(ret, sep):
|
||||
for i in range(len(ret) - 1, 0, -1):
|
||||
ret.insert(i, nodes.Text(sep))
|
||||
return ret
|
||||
|
||||
|
||||
def format_usage_arguments(arguments, base_length=None):
|
||||
line = []
|
||||
prev_argument = None
|
||||
arg_indexes = [0]
|
||||
arguments = arguments[:]
|
||||
while arguments:
|
||||
argument = arguments.pop(0)
|
||||
if isinstance(argument, nodes.Text):
|
||||
line += [argument]
|
||||
continue
|
||||
can_join_arguments = (
|
||||
argument.is_short_option
|
||||
and prev_argument
|
||||
and prev_argument.can_be_joined
|
||||
and prev_argument.required == argument.required
|
||||
)
|
||||
if (
|
||||
prev_argument
|
||||
and not prev_argument.required
|
||||
and prev_argument.can_be_joined
|
||||
and not can_join_arguments
|
||||
):
|
||||
line.append(nodes.Text(']'))
|
||||
arg_indexes.append(len(line))
|
||||
if isinstance(argument, AutoManGroup):
|
||||
arguments = (
|
||||
[nodes.Text(' (')]
|
||||
+ insert_separators(argument.arguments[:], nodes.Text(' |'))
|
||||
+ [nodes.Text(' )')]
|
||||
+ arguments
|
||||
)
|
||||
else:
|
||||
if not can_join_arguments:
|
||||
line.append(nodes.Text(' '))
|
||||
with SurroundWith(line, not argument.required and not argument.can_be_joined):
|
||||
if argument.can_be_joined and not can_join_arguments and not argument.required:
|
||||
line.append(nodes.Text('['))
|
||||
if argument.is_option:
|
||||
line.append(nodes.strong())
|
||||
name = argument.names[0]
|
||||
if can_join_arguments:
|
||||
name = name[1:]
|
||||
# `--` is automatically transformed into – (EN DASH)
|
||||
# when parsing into HTML. We do not need this.
|
||||
line[-1] += [nodes.Text(char) for char in name]
|
||||
if argument.nargs:
|
||||
assert(argument.nargs in (1, '?'))
|
||||
with SurroundWith(line, argument.nargs == '?' and argument.is_option):
|
||||
if argument.is_long_option:
|
||||
line.append(nodes.Text('='))
|
||||
line.append(nodes.emphasis(text=argument.metavar))
|
||||
elif not argument.is_option:
|
||||
line.append(nodes.strong(text=argument.metavar))
|
||||
if argument.multi:
|
||||
line.append(nodes.Text('…'))
|
||||
prev_argument = argument
|
||||
if (
|
||||
prev_argument
|
||||
and prev_argument.can_be_joined
|
||||
and not prev_argument.required
|
||||
):
|
||||
line.append(nodes.Text(']'))
|
||||
arg_indexes.append(len(line))
|
||||
ret = []
|
||||
if base_length is None:
|
||||
ret = line
|
||||
else:
|
||||
length = base_length
|
||||
prev_arg_idx = arg_indexes.pop(0)
|
||||
while arg_indexes:
|
||||
next_arg_idx = arg_indexes.pop(0)
|
||||
arg_length = sum((len(element.astext()) for element in line[prev_arg_idx:next_arg_idx]))
|
||||
if length + arg_length > 68:
|
||||
ret.append(nodes.Text('\n' + (' ' * base_length)))
|
||||
length = base_length
|
||||
ret += line[prev_arg_idx:next_arg_idx]
|
||||
length += arg_length
|
||||
prev_arg_idx = next_arg_idx
|
||||
return ret
|
||||
|
||||
|
||||
LITERAL_RE = re.compile(r"`(.*?)'")
|
||||
|
||||
|
||||
def parse_argparse_text(text):
|
||||
rst_text = LITERAL_RE.subn(r'``\1``', text)[0]
|
||||
ret = []
|
||||
for i, text in enumerate(rst_text.split('``')):
|
||||
if i % 2 == 0:
|
||||
ret.append(nodes.Text(text))
|
||||
else:
|
||||
ret.append(nodes.literal(text=text))
|
||||
return ret
|
||||
|
||||
|
||||
def flatten_groups(arguments):
|
||||
for argument in arguments:
|
||||
if isinstance(argument, AutoManGroup):
|
||||
for group_argument in flatten_groups(argument.arguments):
|
||||
yield group_argument
|
||||
else:
|
||||
yield argument
|
||||
|
||||
|
||||
def format_arguments(arguments):
|
||||
return [nodes.definition_list(
|
||||
'', *[
|
||||
nodes.definition_list_item(
|
||||
'',
|
||||
nodes.term(
|
||||
# node.Text('') is required because otherwise for some
|
||||
# reason first name node is seen in HTML output as
|
||||
# `<strong>abc</strong>`.
|
||||
'', *([nodes.Text('')] + (
|
||||
insert_separators([
|
||||
nodes.strong('', '', *[nodes.Text(ch) for ch in name])
|
||||
for name in argument.names
|
||||
], ', ')
|
||||
if argument.is_option else
|
||||
# Unless node.Text('') is here metavar is written in
|
||||
# bold in the man page.
|
||||
[nodes.Text(''), nodes.emphasis(text=argument.metavar)]
|
||||
) + (
|
||||
[] if not argument.is_option or not argument.nargs else
|
||||
[nodes.Text(' '), nodes.emphasis('', argument.metavar)]
|
||||
))
|
||||
),
|
||||
nodes.definition('', nodes.paragraph('', *parse_argparse_text(argument.help or ''))),
|
||||
)
|
||||
for argument in flatten_groups(arguments)
|
||||
] + [
|
||||
nodes.definition_list_item(
|
||||
'',
|
||||
nodes.term(
|
||||
'', nodes.Text(''),
|
||||
nodes.strong(text='-h'),
|
||||
nodes.Text(', '),
|
||||
nodes.strong('', '', nodes.Text('-'), nodes.Text('-help')),
|
||||
),
|
||||
nodes.definition('', nodes.paragraph('', nodes.Text('Display help and exit.')))
|
||||
)
|
||||
]
|
||||
)]
|
||||
|
||||
|
||||
def format_subcommand_usage(arguments, subcommands, progname, base_length):
|
||||
return reduce((lambda a, b: a + reduce((lambda c, d: c + d), b, [])), [
|
||||
[
|
||||
[progname]
|
||||
+ format_usage_arguments(arguments)
|
||||
+ [nodes.Text(' '), nodes.strong(text=subcmd)]
|
||||
+ format_usage_arguments(subparser.arguments)
|
||||
+ [nodes.Text('\n')]
|
||||
for subcmd, subparser in subparsers.parsers
|
||||
]
|
||||
for subparsers in subcommands
|
||||
], [])
|
||||
|
||||
|
||||
def format_subcommands(subcommands):
|
||||
return reduce((lambda a, b: a + reduce((lambda c, d: c + d), b, [])), [
|
||||
[
|
||||
[
|
||||
nodes.section(
|
||||
'',
|
||||
nodes.title(text='Arguments specific to ' + subcmd + ' subcommand'),
|
||||
*format_arguments(subparser.arguments),
|
||||
ids=['subcmd-' + subcmd]
|
||||
)
|
||||
]
|
||||
for subcmd, subparser in subparsers.parsers
|
||||
]
|
||||
for subparsers in subcommands
|
||||
], [])
|
||||
|
||||
|
||||
class AutoManParser(object):
|
||||
def __init__(self, description=None, help=None):
|
||||
self.description = description
|
||||
self.help = help
|
||||
self.arguments = []
|
||||
self.subcommands = []
|
||||
|
||||
def add_argument(self, *args, **kwargs):
|
||||
self.arguments.append(parse_argument(*args, **kwargs))
|
||||
|
||||
def add_subparsers(self):
|
||||
self.subcommands.append(AutoManSubparsers())
|
||||
return self.subcommands[-1]
|
||||
|
||||
def add_mutually_exclusive_group(self):
|
||||
self.arguments.append(AutoManGroup())
|
||||
return self.arguments[-1]
|
||||
|
||||
def automan_usage(self, prog):
|
||||
block = nodes.literal_block()
|
||||
progname = nodes.strong()
|
||||
progname += [nodes.Text(prog)]
|
||||
base_length = len(prog)
|
||||
if self.subcommands:
|
||||
block += format_subcommand_usage(self.arguments, self.subcommands, progname, base_length)
|
||||
else:
|
||||
block += [progname]
|
||||
block += format_usage_arguments(self.arguments, base_length)
|
||||
return [block]
|
||||
|
||||
def automan_description(self):
|
||||
ret = []
|
||||
if self.help:
|
||||
ret += parse_argparse_text(self.help)
|
||||
ret += format_arguments(self.arguments) + format_subcommands(self.subcommands)
|
||||
return ret
|
||||
|
||||
|
||||
class AutoMan(Directive):
|
||||
required_arguments = 1
|
||||
optional_arguments = 0
|
||||
option_spec = dict(prog=unchanged_required)
|
||||
has_content = False
|
||||
|
||||
def run(self):
|
||||
module = self.arguments[0]
|
||||
template_args = {}
|
||||
template_args.update(get_authors())
|
||||
get_argparser = __import__(str(module), fromlist=[str('get_argparser')]).get_argparser
|
||||
parser = get_argparser(AutoManParser)
|
||||
synopsis_section = nodes.section(
|
||||
'',
|
||||
nodes.title(text='Synopsis'),
|
||||
ids=['synopsis-section'],
|
||||
)
|
||||
synopsis_section += parser.automan_usage(self.options['prog'])
|
||||
description_section = nodes.section(
|
||||
'', nodes.title(text='Description'),
|
||||
ids=['description-section'],
|
||||
)
|
||||
description_section += parser.automan_description()
|
||||
author_section = nodes.section(
|
||||
'', nodes.title(text='Author'),
|
||||
nodes.paragraph(
|
||||
'',
|
||||
nodes.Text('Written by {authors} and contributors. The glyphs in the font patcher are created by {glyphs_author}.'.format(
|
||||
**get_authors()
|
||||
))
|
||||
),
|
||||
ids=['author-section']
|
||||
)
|
||||
issues_url = 'https://github.com/Lokaltog/powerline/issues'
|
||||
reporting_bugs_section = nodes.section(
|
||||
'', nodes.title(text='Reporting bugs'),
|
||||
nodes.paragraph(
|
||||
'',
|
||||
nodes.Text('Report {prog} bugs to '.format(
|
||||
prog=self.options['prog'])),
|
||||
nodes.reference(
|
||||
issues_url, issues_url,
|
||||
refuri=issues_url,
|
||||
internal=False,
|
||||
),
|
||||
nodes.Text('.'),
|
||||
),
|
||||
ids=['reporting-bugs-section']
|
||||
)
|
||||
return [synopsis_section, description_section, author_section, reporting_bugs_section]
|
||||
|
||||
|
||||
def setup(app):
|
||||
app.add_directive('automan', AutoMan)
|
|
@ -65,6 +65,7 @@ def get_argparser(ArgumentParser=ConfigArgParser):
|
|||
nargs='?',
|
||||
choices=('tmux', 'prompt'),
|
||||
metavar='COMPONENT',
|
||||
help='Only applicable for `uses\' subcommand: makes `powerline-config\' exit with 0 if specific component is enabled and with 1 otherwise. `tmux\' component stands for tmux bindings (e.g. those that notify tmux about current directory changes), `prompt\' component stands for shell prompt.'
|
||||
)
|
||||
shell_parser.add_argument(
|
||||
'-s', '--shell',
|
||||
|
|
|
@ -41,7 +41,7 @@ def get_argparser(ArgumentParser=argparse.ArgumentParser):
|
|||
parser.add_argument('--jobnum', metavar='INT', type=int, help='Number of jobs.')
|
||||
parser.add_argument('-c', '--config', metavar='KEY.KEY=VALUE', action='append', help='Configuration overrides for `config.json\'. Is translated to a dictionary and merged with the dictionary obtained from actual JSON configuration: KEY.KEY=VALUE is translated to `{"KEY": {"KEY": VALUE}}\' and then merged recursively. VALUE may be any JSON value, values that are not `null\', `true\', `false\', start with digit, `{\', `[\' are treated like strings. If VALUE is omitted then corresponding key is removed.')
|
||||
parser.add_argument('-t', '--theme_option', metavar='THEME.KEY.KEY=VALUE', action='append', help='Like above, but theme-specific. THEME should point to an existing and used theme to have any effect, but it is fine to use any theme here.')
|
||||
parser.add_argument('-R', '--renderer_arg', metavar='KEY=VAL', action='append', help='Like above, but provides argument for renderer. Is supposed to be used only by shell bindings to provide various data like last_exit_code or last_pipe_status (they are not using --renderer_arg for historical resons: renderer_arg was added later).')
|
||||
parser.add_argument('-R', '--renderer_arg', metavar='KEY=VAL', action='append', help='Like above, but provides argument for renderer. Is supposed to be used only by shell bindings to provide various data like last_exit_code or last_pipe_status (they are not using `--renderer_arg\' for historical resons: `--renderer_arg\' was added later).')
|
||||
parser.add_argument('-p', '--config_path', action='append', metavar='PATH', help='Path to configuration directory. If it is present then configuration files will only be seeked in the provided path. May be provided multiple times to search in a list of directories.')
|
||||
parser.add_argument('--socket', metavar='ADDRESS', type=str, help='Socket address to use in daemon clients. Is always UNIX domain socket on linux and file socket on Mac OS X. Not used here, present only for compatibility with other powerline clients. This argument must always be the first one and be in a form `--socket ADDRESS\': no `=\' or short form allowed (in other powerline clients, not here).')
|
||||
return parser
|
||||
|
|
Loading…
Reference in New Issue