commit
f04a64feef
|
@ -0,0 +1,45 @@
|
|||
Command Line Arguments
|
||||
======================
|
||||
|
||||
When starting vimiv form the command line you have the ability to pass a number of
|
||||
different argument to vimiv.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
In the following we present a few use cases of command line arguments.
|
||||
|
||||
* Start in library view with the thumbnail grid displayed::
|
||||
|
||||
vimiv * --command "enter thumbnail" --command "enter library"
|
||||
|
||||
* Start in read-only mode. This prevents accidental modification (renaming, moving, editing etc.) of any images::
|
||||
|
||||
vimiv --set read_only true
|
||||
|
||||
* Change WM_CLASS_INSTANCE to identify a vimiv instance::
|
||||
|
||||
vimiv --qt-args "--name myVimivInstance"
|
||||
|
||||
* Print the last selected image to STDOUT when quitting::
|
||||
|
||||
vimiv --output "%"
|
||||
|
||||
* Use vimiv as *Rofi for Images* to make a selection from candidate images::
|
||||
|
||||
mySel=$(echo $myCand | vimiv --input --output "%m" --command "enter thumbnail")
|
||||
|
||||
* Print debug logs of your amazing plugin you are writing and of the `api._mark` module which does not behave as you are expecting::
|
||||
|
||||
vimiv --debug myAmazingPlugin api._mark
|
||||
|
||||
Command Line Arguments
|
||||
----------------------
|
||||
|
||||
The general calling structure is:
|
||||
|
||||
.. include:: synopsis.rstsrc
|
||||
|
||||
The following is an exhaustive list of all available arguments:
|
||||
|
||||
.. include:: options.rstsrc
|
|
@ -10,6 +10,7 @@ The following documents are available:
|
|||
getting_started
|
||||
commands
|
||||
configuration/index
|
||||
cl_options/index
|
||||
metadata
|
||||
contributing
|
||||
migrating
|
||||
|
|
28
misc/vimiv.1
28
misc/vimiv.1
|
@ -27,12 +27,12 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
|||
.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
|
||||
.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
|
||||
..
|
||||
.TH "VIMIV" "1" "Dec 26, 2021" "" "vimiv"
|
||||
.TH "VIMIV" "1" "Jan 08, 2022" "" "vimiv"
|
||||
.SH NAME
|
||||
vimiv \- an image viewer with vim-like keybindings
|
||||
.SH SYNOPSIS
|
||||
.sp
|
||||
\fBvimiv\fP [\fBPATH\fP] [\fB\-h\fP] [\fB\-\-help\fP] [\fB\-f\fP] [\fB\-\-fullscreen\fP] [\fB\-v\fP] [\fB\-\-version\fP] [\fB\-g\fP \fIWIDTHxHEIGHT\fP] [\fB\-\-geometry\fP \fIWIDTHxHEIGHT\fP] [\fB\-\-temp\-basedir\fP] [\fB\-\-config\fP \fIFILE\fP] [\fB\-\-keyfile\fP \fIFILE\fP] [\fB\-s\fP \fIOPTION\fP \fIVALUE\fP] [\fB\-\-set\fP \fIOPTION\fP \fIVALUE\fP] [\fB\-\-log\-level\fP \fILEVEL\fP] [\fB\-\-command\fP \fICOMMAND\fP] [\fB\-b\fP \fIDIRECTORY\fP] [\fB\-\-basedir\fP \fIDIRECTORY\fP] [\fB\-o\fP \fITEXT\fP] [\fB\-\-output\fP \fITEXT\fP] [\fB\-i\fP] [\fB\-\-input\fP] [\fB\-\-debug\fP \fIMODULE\fP] [\fB\-\-qt\-args\fP \fIARGS\fP]
|
||||
\fBvimiv\fP [\fBPATH\fP] [\fB\-\-help\fP|\fB\-h\fP] [\fB\-\-fullscreen\fP|\fB\-f\fP] [\fB\-\-version\fP|\fB\-v\fP] [\fB\-\-geometry\fP \fIWIDTHxHEIGHT\fP|\fB\-g\fP \fIWIDTHxHEIGHT\fP] [\fB\-\-temp\-basedir\fP] [\fB\-\-config\fP \fIFILE\fP] [\fB\-\-keyfile\fP \fIFILE\fP] [\fB\-\-set\fP \fIOPTION\fP \fIVALUE\fP|\fB\-s\fP \fIOPTION\fP \fIVALUE\fP] [\fB\-\-log\-level\fP \fILEVEL\fP] [\fB\-\-command\fP \fICOMMAND\fP] [\fB\-\-basedir\fP \fIDIRECTORY\fP|\fB\-b\fP \fIDIRECTORY\fP] [\fB\-\-output\fP \fITEXT\fP|\fB\-o\fP \fITEXT\fP] [\fB\-\-input\fP|\fB\-i\fP] [\fB\-\-debug\fP \fIMODULE\fP] [\fB\-\-qt\-args\fP \fIARGS\fP]
|
||||
.SH DESCRIPTION
|
||||
.sp
|
||||
Vimiv is an image viewer with vim\-like keybindings. It is written in python3
|
||||
|
@ -54,7 +54,7 @@ Complete customization with style sheets
|
|||
A much more complete documentation can be found under
|
||||
\fI\%https://karlch.github.io/vimiv\-qt/\fP\&.
|
||||
.SH OPTIONS
|
||||
.SS positional arguments
|
||||
.SS POSITIONAL ARGUMENTS
|
||||
.sp
|
||||
\fBPATH\fP
|
||||
.INDENT 0.0
|
||||
|
@ -62,30 +62,30 @@ A much more complete documentation can be found under
|
|||
Paths to open
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SS optional arguments
|
||||
.SS OPTIONS
|
||||
.sp
|
||||
\fB\-h\fP, \fB\-\-help\fP
|
||||
\fB\-\-help\fP, \fB\-h\fP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
show this help message and exit
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
\fB\-f\fP, \fB\-\-fullscreen\fP
|
||||
\fB\-\-fullscreen\fP, \fB\-f\fP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
Start fullscreen
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
\fB\-v\fP, \fB\-\-version\fP
|
||||
\fB\-\-version\fP, \fB\-v\fP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
Print version information and exit
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
\fB\-g\fP \fIWIDTHxHEIGHT\fP, \fB\-\-geometry\fP \fIWIDTHxHEIGHT\fP
|
||||
\fB\-\-geometry\fP \fIWIDTHxHEIGHT\fP, \fB\-g\fP \fIWIDTHxHEIGHT\fP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
Set the starting geometry
|
||||
|
@ -113,7 +113,7 @@ Use FILE as keybinding file
|
|||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
\fB\-s\fP \fIOPTION\fP \fIVALUE\fP, \fB\-\-set\fP \fIOPTION\fP \fIVALUE\fP
|
||||
\fB\-\-set\fP \fIOPTION\fP \fIVALUE\fP, \fB\-s\fP \fIOPTION\fP \fIVALUE\fP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
Set a temporary setting
|
||||
|
@ -134,27 +134,27 @@ Run COMMAND on startup, usable multiple times
|
|||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
\fB\-b\fP \fIDIRECTORY\fP, \fB\-\-basedir\fP \fIDIRECTORY\fP
|
||||
\fB\-\-basedir\fP \fIDIRECTORY\fP, \fB\-b\fP \fIDIRECTORY\fP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
Directory to use for all storage
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
\fB\-o\fP \fITEXT\fP, \fB\-\-output\fP \fITEXT\fP
|
||||
\fB\-\-output\fP \fITEXT\fP, \fB\-o\fP \fITEXT\fP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
Wildcard expanded string to print to standard output upon quit
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.sp
|
||||
\fB\-i\fP, \fB\-\-input\fP
|
||||
\fB\-\-input\fP, \fB\-i\fP
|
||||
.INDENT 0.0
|
||||
.INDENT 3.5
|
||||
Read paths to open from standard input
|
||||
.UNINDENT
|
||||
.UNINDENT
|
||||
.SS development arguments
|
||||
.SS DEVELOPMENT ARGUMENTS
|
||||
.sp
|
||||
\fB\-\-debug\fP \fIMODULE\fP
|
||||
.INDENT 0.0
|
||||
|
@ -175,6 +175,6 @@ Arguments to pass to qt directly, use quotes to pass multiple arguments
|
|||
.SH AUTHOR
|
||||
Christian Karl
|
||||
.SH COPYRIGHT
|
||||
2017-2021, Christian Karl
|
||||
2017-2022, Christian Karl
|
||||
.\" Generated by docutils manpage writer.
|
||||
.
|
||||
|
|
|
@ -50,17 +50,24 @@ class RSTFile:
|
|||
title: Title of the table.
|
||||
"""
|
||||
# Find out size of first column
|
||||
length = max([len(elem[0]) for elem in rows])
|
||||
ncols = len(rows[0])
|
||||
lengths = [max([len(elem[i]) for elem in rows]) for i in range(ncols)]
|
||||
empty_row = ["=" * n for n in lengths]
|
||||
|
||||
def format_row(row=empty_row):
|
||||
parts = " ".join(f"{elem:{n}s}" for elem, n in zip(row, lengths))
|
||||
return f" {parts}\n"
|
||||
|
||||
# Header
|
||||
self.write(".. table:: %s\n :widths: %s\n\n" % (title, widths))
|
||||
self.write(" %s ===========\n" % (length * "="))
|
||||
self.write(" %-*s %s\n" % (length, rows[0][0], rows[0][1]))
|
||||
self.write(" %s ===========\n" % (length * "="))
|
||||
self.write(f".. table:: {title}\n :widths: {widths}\n\n")
|
||||
self.write(format_row())
|
||||
self.write(format_row(rows[0]))
|
||||
self.write(format_row())
|
||||
# Content
|
||||
for row in rows[1:]:
|
||||
self.write(" %-*s %s\n" % (length, row[0], row[1]))
|
||||
self.write(format_row(row))
|
||||
# Footer
|
||||
self.write(" %s ===========\n" % (length * "="))
|
||||
self.write(format_row())
|
||||
|
||||
def _write_header(self):
|
||||
"""Write header to file explaining that the file was autogenerated."""
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
|
||||
"""Generate reST documentation from source code docstrings."""
|
||||
|
||||
import collections
|
||||
import inspect
|
||||
import importlib
|
||||
import os
|
||||
import sys
|
||||
import textwrap
|
||||
from typing import Any, Dict, List, NamedTuple
|
||||
|
||||
# Startup is imported to create all the commands and keybindings via their decorators
|
||||
from vimiv import api, parser, startup # pylint: disable=unused-import
|
||||
|
@ -65,12 +68,15 @@ def generate_settings():
|
|||
print("generating settings...")
|
||||
filename = "docs/documentation/configuration/settings_table.rstsrc"
|
||||
with RSTFile(filename) as f:
|
||||
rows = [("Setting", "Description")]
|
||||
rows = [("Setting", "Description", "Default", "Type")]
|
||||
for name in sorted(api.settings._storage.keys()):
|
||||
setting = api.settings._storage[name]
|
||||
if setting.desc: # Otherwise the setting is meant to be hidden
|
||||
rows.append((name, setting.desc))
|
||||
f.write_table(rows, title="Overview of settings", widths="30 70")
|
||||
default = str(setting.default)
|
||||
if len(default) > 20: # Cut very long defaults (exif)
|
||||
default = default[:17] + "..."
|
||||
rows.append((name, setting.desc, default, setting.typ.__name__))
|
||||
f.write_table(rows, title="Overview of settings", widths="20 60 15 5")
|
||||
|
||||
|
||||
def generate_keybindings():
|
||||
|
@ -93,105 +99,173 @@ def _gen_keybinding_rows(bindings):
|
|||
|
||||
def generate_commandline_options():
|
||||
"""Generate file including the command line options."""
|
||||
|
||||
argparser = parser.get_argparser()
|
||||
groups, titles = _get_options(argparser)
|
||||
# Synopsis
|
||||
arguments = _get_arguments(argparser)
|
||||
|
||||
# Synopsis Man Page
|
||||
filename_synopsis = "docs/manpage/synopsis.rstsrc"
|
||||
with open(filename_synopsis, "w", encoding="utf-8") as f:
|
||||
synopsis_options = ["[%s]" % (title) for title in titles]
|
||||
synopsis = "**vimiv** %s" % (" ".join(synopsis_options))
|
||||
f.write(synopsis)
|
||||
# Options
|
||||
f.write(_generate_synopsis(arguments, emph="*", sep=r"\ \|\ "))
|
||||
|
||||
# Synopsis Documentation
|
||||
filename_synopsis = "docs/documentation/cl_options/synopsis.rstsrc"
|
||||
with open(filename_synopsis, "w", encoding="utf-8") as f:
|
||||
raw_synopsis_doc = _generate_synopsis(arguments)
|
||||
synopsis_doc = "\n ".join(textwrap.wrap(raw_synopsis_doc, width=79))
|
||||
f.write(f".. code-block::\n\n {synopsis_doc}")
|
||||
|
||||
# Command Listing
|
||||
groups = collections.defaultdict(list)
|
||||
for arg in arguments:
|
||||
groups[arg.group].append(arg)
|
||||
|
||||
# Command Listing Man Page
|
||||
filename_options = "docs/manpage/options.rstsrc"
|
||||
with RSTFile(filename_options) as f:
|
||||
for title, argstr in groups.items():
|
||||
f.write_section(title)
|
||||
f.write(argstr)
|
||||
_generate_cli_man(groups, f)
|
||||
|
||||
# Command Listing Documentation
|
||||
filename_options = "docs/documentation/cl_options/options.rstsrc"
|
||||
with RSTFile(filename_options) as f:
|
||||
_generate_cli_doc(groups, f)
|
||||
|
||||
|
||||
def _get_options(argparser):
|
||||
"""Retrieve the options from the argument parser.
|
||||
class ParserArgument(NamedTuple):
|
||||
"""Storage class for a single command line argument."""
|
||||
|
||||
Returns:
|
||||
groups: Dictionary of group titles and argument strings.
|
||||
titles: List containing all argument titles.
|
||||
"""
|
||||
groups = {}
|
||||
titles = []
|
||||
for group in argparser._action_groups:
|
||||
argstr = ""
|
||||
for action in group._group_actions:
|
||||
argstr += (
|
||||
_format_positional(action, titles)
|
||||
if "positional" in group.title
|
||||
else _format_optional(action, titles)
|
||||
)
|
||||
groups[group.title] = argstr
|
||||
return groups, titles
|
||||
group: str
|
||||
longname: str
|
||||
shortname: str
|
||||
metavar: Any
|
||||
description: str
|
||||
|
||||
@property
|
||||
def is_positional(self):
|
||||
return self.longname is self.shortname is None
|
||||
|
||||
def get_names(self, formatter: str) -> List[str]:
|
||||
"""Retrieve list of long and shortname which are not None."""
|
||||
return [
|
||||
self._format(name, formatter)
|
||||
for name in [self.longname, self.shortname]
|
||||
if name is not None
|
||||
]
|
||||
|
||||
def get_metavar(self, formatter: str) -> str:
|
||||
"""Retrieve metavar."""
|
||||
if self.metavar is None:
|
||||
return ""
|
||||
if isinstance(self.metavar, tuple):
|
||||
return " ".join(self._format(e, formatter) for e in self.metavar)
|
||||
return self._format(self.metavar, formatter)
|
||||
|
||||
def get_name_metavar(
|
||||
self, name_formatter: str, metavar_formatter: str
|
||||
) -> List[str]:
|
||||
"""Retrieve all not-none names and append metavar."""
|
||||
names = self.get_names(name_formatter)
|
||||
metavar = self.get_metavar(metavar_formatter)
|
||||
lst = names if names else [metavar]
|
||||
return [f"{e} {metavar}" if metavar else e for e in lst]
|
||||
|
||||
def _format(self, element: str, formatter: str) -> str:
|
||||
"""Wrap the element into the format string."""
|
||||
return formatter + element + formatter
|
||||
|
||||
|
||||
def _format_optional(action, titles):
|
||||
"""Format optional argument neatly.
|
||||
def _get_arguments(argparser: parser.argparse.ArgumentParser) -> List[ParserArgument]:
|
||||
"""Retrieve all arguments from the passed argparser.
|
||||
|
||||
Args:
|
||||
action: The argparser action.
|
||||
titles: List of titles to update with the title(s) of this argument.
|
||||
argparser: Argument parser where the arguments get extracted from.
|
||||
|
||||
Returns:
|
||||
Formatted string of this argument.
|
||||
List of ParserArgument where each element represents one argument of the parser.
|
||||
"""
|
||||
_titles = _format_optional_title(action)
|
||||
titles.extend(_titles)
|
||||
title = ", ".join(_titles)
|
||||
desc = action.help
|
||||
return _format_option(title, desc)
|
||||
|
||||
def argument_from_action(group, action):
|
||||
if len(action.option_strings) == 2:
|
||||
shortname, longname = action.option_strings
|
||||
elif len(action.option_strings) == 1:
|
||||
longname = action.option_strings[0]
|
||||
shortname = None
|
||||
else:
|
||||
longname = shortname = None
|
||||
return ParserArgument(
|
||||
group=group.title,
|
||||
longname=longname,
|
||||
shortname=shortname,
|
||||
metavar=action.metavar,
|
||||
description=action.help,
|
||||
)
|
||||
|
||||
return [
|
||||
argument_from_action(group, action)
|
||||
for group in argparser._action_groups
|
||||
for action in group._group_actions
|
||||
]
|
||||
|
||||
|
||||
def _format_positional(action, titles):
|
||||
"""Format positional argument neatly.
|
||||
def _generate_synopsis(arguments: List[ParserArgument], emph: str = "", sep="|") -> str:
|
||||
"""Generate formatted synopsis of vimiv.
|
||||
|
||||
Args:
|
||||
action: The argparser action.
|
||||
titles: List of titles to update with the title of this argument.
|
||||
arguments: List of instances of ParserArgument.
|
||||
emph: Character used for emphasis.
|
||||
sep: String used to separate different versions of the same argument, e.g. -o
|
||||
and --output.
|
||||
Returns:
|
||||
Formatted string of this argument.
|
||||
Formatted synopsis for the man page.
|
||||
"""
|
||||
title = "**%s**" % (action.metavar)
|
||||
titles.append(title)
|
||||
desc = action.help
|
||||
return _format_option(title, desc)
|
||||
emph2 = 2 * emph
|
||||
synopsis = f"{emph2}vimiv{emph2}"
|
||||
for arg in arguments:
|
||||
if arg.is_positional:
|
||||
synopsis += f" [{arg.get_metavar(emph2)}]"
|
||||
else:
|
||||
command = sep.join(arg.get_name_metavar(emph2, emph))
|
||||
synopsis += f" [{command}]"
|
||||
return synopsis
|
||||
|
||||
|
||||
def _format_option(title, desc):
|
||||
"""Format an option neatly.
|
||||
def _generate_cli_man(groups: Dict[str, List[ParserArgument]], f: RSTFile) -> None:
|
||||
"""Generate commands listing with man page formatting.
|
||||
|
||||
Args:
|
||||
title: The title of this option.
|
||||
desc: The help description of this option.
|
||||
groups: List of ParserArgument sorted by their respective group.
|
||||
f: RSTFile to write to.
|
||||
"""
|
||||
return "%s\n\n %s\n\n" % (title, desc)
|
||||
for group in groups.keys():
|
||||
arguments = groups[group]
|
||||
|
||||
f.write_section(group.upper())
|
||||
for arg in arguments:
|
||||
if arg.is_positional:
|
||||
f.write(f"{arg.get_metavar('**')}\n\n\t{arg.description}\n\n")
|
||||
else:
|
||||
f.write(f"{', '.join(arg.get_name_metavar('**', '*'))}\n\n")
|
||||
f.write(f"\t{arg.description}\n\n")
|
||||
|
||||
|
||||
def _format_optional_title(action):
|
||||
"""Format the title of an optional argument neatly.
|
||||
|
||||
The title depends on the number of arguments this action requires.
|
||||
def _generate_cli_doc(groups: Dict[str, List[ParserArgument]], f: RSTFile) -> None:
|
||||
"""Generate commands listing with documentation formatting.
|
||||
|
||||
Args:
|
||||
action: The argparser action.
|
||||
Returns:
|
||||
Formatted title string of this argument.
|
||||
groups: List of ParserArgument sorted by their respective group.
|
||||
f: RSTFile to write to.
|
||||
"""
|
||||
formats = []
|
||||
for option in action.option_strings:
|
||||
if isinstance(action.metavar, str): # One argument
|
||||
title = "**%s** *%s*" % (option, action.metavar)
|
||||
elif isinstance(action.metavar, tuple): # Multiple arguments
|
||||
elems = ["*%s*" % (elem) for elem in action.metavar]
|
||||
title = "**%s** %s" % (option, " ".join(elems))
|
||||
else: # No arguments
|
||||
title = "**%s**" % (option)
|
||||
formats.append(title)
|
||||
return formats
|
||||
for group in groups.keys():
|
||||
arguments = groups[group]
|
||||
|
||||
rows = [("Command", "Description")]
|
||||
for arg in arguments:
|
||||
if arg.is_positional:
|
||||
name = arg.get_metavar("``")
|
||||
else:
|
||||
name = ", ".join(f"``{e}``" for e in arg.get_name_metavar("", ""))
|
||||
rows.append((name, arg.description))
|
||||
f.write_table(rows, title=group.capitalize(), widths="50 50")
|
||||
|
||||
|
||||
def generate_plugins():
|
||||
|
|
Loading…
Reference in New Issue