From 65539403288c984c5175a612c9519437742fc95c Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Mon, 5 Feb 2018 18:45:45 -0500 Subject: doc: generate man page This commit uses the recent refactoring for defining flags to automatically generate a man page. This finally allows us to define the documentation for each flag in a single place. The man page is generated on every build, if and only if `asciidoc` is installed. When generated, it is placed in Cargo's `OUT_DIR` directory, which is the same place that shell completions live. --- .travis.yml | 2 + build.rs | 128 +++++++++- ci/before_deploy.sh | 22 +- doc/convert-to-man | 5 - doc/rg.1 | 692 ---------------------------------------------------- doc/rg.1.md | 456 ---------------------------------- doc/rg.1.txt.tpl | 136 +++++++++++ src/app.rs | 25 +- 8 files changed, 292 insertions(+), 1174 deletions(-) delete mode 100755 doc/convert-to-man delete mode 100644 doc/rg.1 delete mode 100644 doc/rg.1.md create mode 100644 doc/rg.1.txt.tpl diff --git a/.travis.yml b/.travis.yml index bf2b3f55..aaaa3dd1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,8 @@ addons: - zsh # Needed for testing decompression search. - xz-utils + # For generating man page. + - asciidoc matrix: fast_finish: true include: diff --git a/build.rs b/build.rs index 01b3d18e..93c25858 100644 --- a/build.rs +++ b/build.rs @@ -4,11 +4,15 @@ extern crate clap; extern crate lazy_static; use std::env; -use std::fs; +use std::fs::{self, File}; +use std::io::{self, Read, Write}; +use std::path::Path; use std::process; use clap::Shell; +use app::{RGArg, RGArgKind}; + #[allow(dead_code)] #[path = "src/app.rs"] mod app; @@ -27,6 +31,9 @@ fn main() { } }; fs::create_dir_all(&outdir).unwrap(); + if let Err(err) = generate_man_page(&outdir) { + eprintln!("failed to generate man page: {}", err); + } // Use clap to build completion files. let mut app = app::app(); @@ -37,11 +44,124 @@ fn main() { // are manually maintained in `complete/_rg`. // Make the current git hash available to the build. + if let Some(rev) = git_revision_hash() { + println!("cargo:rustc-env=RIPGREP_BUILD_GIT_HASH={}", rev); + } +} + +fn git_revision_hash() -> Option { let result = process::Command::new("git") .args(&["rev-parse", "--short=10", "HEAD"]) .output(); - if let Ok(output) = result { - let hash = String::from_utf8_lossy(&output.stdout); - println!("cargo:rustc-env=RIPGREP_BUILD_GIT_HASH={}", hash); + result.ok().map(|output| { + String::from_utf8_lossy(&output.stdout).trim().to_string() + }) +} + +fn generate_man_page>(outdir: P) -> io::Result<()> { + // If asciidoc isn't installed, then don't do anything. + if let Err(err) = process::Command::new("a2x").output() { + eprintln!("Could not run 'a2x' binary, skipping man page generation."); + eprintln!("Error from running 'a2x': {}", err); + return Ok(()); + } + let outdir = outdir.as_ref(); + let cwd = env::current_dir()?; + let tpl_path = cwd.join("doc").join("rg.1.txt.tpl"); + let txt_path = outdir.join("rg.1.txt"); + + let mut tpl = String::new(); + File::open(&tpl_path)?.read_to_string(&mut tpl)?; + tpl = tpl.replace("{OPTIONS}", &formatted_options()?); + + let githash = git_revision_hash(); + let githash = githash.as_ref().map(|x| &**x); + tpl = tpl.replace("{VERSION}", &app::long_version(githash)); + + File::create(&txt_path)?.write_all(tpl.as_bytes())?; + let result = process::Command::new("a2x") + .arg("--no-xmllint") + .arg("--doctype").arg("manpage") + .arg("--format").arg("manpage") + .arg(&txt_path) + .spawn()? + .wait()?; + if !result.success() { + let msg = format!("'a2x' failed with exit code {:?}", result.code()); + return Err(ioerr(msg)); + } + Ok(()) +} + +fn formatted_options() -> io::Result { + let mut args = app::all_args_and_flags(); + args.sort_by(|x1, x2| x1.name.cmp(&x2.name)); + + let mut formatted = vec![]; + for arg in args { + // ripgrep only has two positional arguments, and probably will only + // ever have two positional arguments, so we just hardcode them into + // the template. + if let app::RGArgKind::Positional{..} = arg.kind { + continue; + } + formatted.push(formatted_arg(&arg)?); } + Ok(formatted.join("\n\n")) +} + +fn formatted_arg(arg: &RGArg) -> io::Result { + match arg.kind { + RGArgKind::Positional{..} => panic!("unexpected positional argument"), + RGArgKind::Switch { long, short, multiple } => { + let mut out = vec![]; + + let mut header = format!("--{}", long); + if let Some(short) = short { + header = format!("-{}, {}", short, header); + } + if multiple { + header = format!("*{}* ...::", header); + } else { + header = format!("*{}*::", header); + } + writeln!(out, "{}", header)?; + writeln!(out, "{}", formatted_doc_txt(arg)?)?; + + Ok(String::from_utf8(out).unwrap()) + } + RGArgKind::Flag { long, short, value_name, multiple, .. } => { + let mut out = vec![]; + + let mut header = format!("--{}", long); + if let Some(short) = short { + header = format!("-{}, {}", short, header); + } + if multiple { + header = format!("*{}* _{}_ ...::", header, value_name); + } else { + header = format!("*{}* _{}_::", header, value_name); + } + writeln!(out, "{}", header)?; + writeln!(out, "{}", formatted_doc_txt(arg)?)?; + + Ok(String::from_utf8(out).unwrap()) + } + } +} + +fn formatted_doc_txt(arg: &RGArg) -> io::Result { + let paragraphs: Vec<&str> = arg.doc_long.split("\n\n").collect(); + if paragraphs.is_empty() { + return Err(ioerr(format!("missing docs for --{}", arg.name))); + } + let first = format!(" {}", paragraphs[0].replace("\n", "\n ")); + if paragraphs.len() == 1 { + return Ok(first); + } + Ok(format!("{}\n+\n{}", first, paragraphs[1..].join("\n+\n"))) +} + +fn ioerr(msg: String) -> io::Error { + io::Error::new(io::ErrorKind::Other, msg) } diff --git a/ci/before_deploy.sh b/ci/before_deploy.sh index 35bdc0b1..bef04122 100755 --- a/ci/before_deploy.sh +++ b/ci/before_deploy.sh @@ -20,17 +20,25 @@ mk_tarball() { local gcc_prefix="$(gcc_prefix)" local td="$(mktemp -d)" local name="${PROJECT_NAME}-${TRAVIS_TAG}-${TARGET}" - mkdir -p "$td/$name/complete" - mkdir deployment + local staging="$td/$name" + mkdir -p "$staging/complete" local out_dir="$(pwd)/deployment" - - cp target/$TARGET/release/rg "$td/$name/rg" - "${gcc_prefix}strip" "$td/$name/rg" - cp {doc/rg.1,README.md,UNLICENSE,COPYING,LICENSE-MIT} "$td/$name/" + mkdir -p "$out_dir" + + # Copy the ripgrep binary and strip it. + cp target/$TARGET/release/rg "$staging/rg" + "${gcc_prefix}strip" "$staging/rg" + # Copy the README and licenses. + cp {README.md,UNLICENSE,COPYING,LICENSE-MIT} "$staging/" + # Copy shell completion files. cp \ target/"$TARGET"/release/build/ripgrep-*/out/{rg.bash,rg.fish,_rg.ps1} \ - "$td/$name/complete/" + "$staging/complete/" cp complete/_rg "$td/$name/complete/" + # Copy man page. + cp \ + target/"$TARGET"/release/build/ripgrep-*/out/rg.1 \ + "$td/$name/" (cd "$td" && tar czf "$out_dir/$name.tar.gz" *) rm -rf "$td" diff --git a/doc/convert-to-man b/doc/convert-to-man deleted file mode 100755 index 60761dba..00000000 --- a/doc/convert-to-man +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -e - -pandoc -s -f markdown-smart -t man rg.1.md -o rg.1 -sed -i.bak 's/\.TH.*/.TH "rg" "1"/g' rg.1 -rm -f rg.1.bak # BSD `sed` requires the creation of a back-up file diff --git a/doc/rg.1 b/doc/rg.1 deleted file mode 100644 index b8112463..00000000 --- a/doc/rg.1 +++ /dev/null @@ -1,692 +0,0 @@ -.\" Automatically generated by Pandoc 2.0.6 -.\" -.TH "rg" "1" -.hy -.SH NAME -.PP -rg \- recursively search current directory for lines matching a pattern -.SH SYNOPSIS -.PP -rg [\f[I]OPTIONS\f[]] \f[I]PATTERN\f[] [\f[I]PATH\f[] ...] -.PP -rg [\f[I]OPTIONS\f[]] [\-e \f[I]PATTERN\f[] ...] [\-f \f[I]FILE\f[] ...] -[\f[I]PATH\f[] ...] -.PP -rg [\f[I]OPTIONS\f[]] \-\-files [\f[I]PATH\f[] ...] -.PP -rg [\f[I]OPTIONS\f[]] \-\-type\-list -.PP -rg [\f[I]OPTIONS\f[]] \-\-help -.PP -rg [\f[I]OPTIONS\f[]] \-\-version -.SH DESCRIPTION -.PP -ripgrep (rg) combines the usability of The Silver Searcher (an ack -clone) with the raw speed of grep. -.PP -ripgrep\[aq]s regex engine uses finite automata and guarantees linear -time searching. -Because of this, features like backreferences and arbitrary lookaround -are not supported. -.PP -Note that ripgrep may abort unexpectedly when using default settings if -it searches a file that is simultaneously truncated. -This behavior can be avoided by passing the \-\-no\-mmap flag. -.PP -Project home page: https://github.com/BurntSushi/ripgrep -.SH POSITIONAL ARGUMENTS -.TP -.B \f[I]PATTERN\f[] -A regular expression used for searching. -To match a pattern beginning with a dash, use the \-e/\-\-regexp option. -.RS -.RE -.TP -.B \f[I]PATH\f[] -A file or directory to search. -Directories are searched recursively. -Paths specified expicitly on the command line override glob and ignore -rules. -.RS -.RE -.SH COMMON OPTIONS -.TP -.B \-a, \-\-text -Search binary files as if they were text. -.RS -.RE -.TP -.B \-c, \-\-count -Only show count of line matches for each file. -.RS -.RE -.TP -.B \-\-color \f[I]WHEN\f[] -Whether to use color in the output. -Valid values are never, auto, always or ansi. -The default is auto. -When always is used, coloring is attempted based on your environment. -When ansi is used, coloring is forcefully done using ANSI escape color -codes. -.RS -.RE -.TP -.B \-e, \-\-regexp \f[I]PATTERN\f[] ... -Use PATTERN to search. -This option can be provided multiple times, where all patterns given are -searched. -This is also useful when searching for patterns that start with a dash. -.RS -.RE -.TP -.B \-F, \-\-fixed\-strings -Treat the pattern as a literal string instead of a regular expression. -.RS -.RE -.TP -.B \-g, \-\-glob \f[I]GLOB\f[] ... -Include or exclude files for searching that match the given glob. -This always overrides any other ignore logic if there is a conflict, but -is otherwise applied in addition to ignore files (e.g., .gitignore or -\&.ignore). -Multiple glob flags may be used. -Globbing rules match .gitignore globs. -Precede a glob with a \[aq]!\[aq] to exclude it. -.RS -.PP -The \-\-glob flag subsumes the functionality of both the \-\-include and -\-\-exclude flags commonly found in other tools. -.PP -Values given to \-g must be quoted or your shell will expand them and -result in unexpected behavior. -.PP -Combine with the \-\-files flag to return matched filenames (i.e., to -replicate ack/ag\[aq]s \-g flag). -For example: -.IP -.nf -\f[C] -rg\ \-g\ \[aq]*.foo\[aq]\ \-\-files -\f[] -.fi -.RE -.TP -.B \-h, \-\-help -Show this usage message. -.RS -.RE -.TP -.B \-i, \-\-ignore\-case -Case insensitive search. -Overridden by \-\-case\-sensitive. -.RS -.RE -.TP -.B \-n, \-\-line\-number -Show line numbers (1\-based). -This is enabled by default at a tty. -.RS -.RE -.TP -.B \-N, \-\-no\-line\-number -Suppress line numbers. -.RS -.RE -.TP -.B \-q, \-\-quiet -Do not print anything to stdout. -If a match is found in a file, stop searching that file. -.RS -.RE -.TP -.B \-t, \-\-type \f[I]TYPE\f[] ... -Only search files matching TYPE. -Multiple type flags may be provided. -Use the \-\-type\-list flag to list all available types. -.RS -.RE -.TP -.B \-T, \-\-type\-not \f[I]TYPE\f[] ... -Do not search files matching TYPE. -Multiple not\-type flags may be provided. -.RS -.RE -.TP -.B \-u, \-\-unrestricted ... -Reduce the level of \[aq]smart\[aq] searching. -A single \-u doesn\[aq]t respect .gitignore (etc.) files. -Two \-u flags will search hidden files and directories. -Three \-u flags will search binary files. -\-uu is equivalent to \f[C]grep\ \-r\f[], and \-uuu is equivalent to -\f[C]grep\ \-a\ \-r\f[]. -.RS -.PP -Note that the \-u flags are convenient aliases for other combinations of -flags. -\-u aliases \-\-no\-ignore. -\-uu aliases \-\-no\-ignore \-\-hidden. -\-uuu aliases \-\-no\-ignore \-\-hidden \-\-text. -.RE -.TP -.B \-v, \-\-invert\-match -Invert matching. -.RS -.RE -.TP -.B \-w, \-\-word\-regexp -Only show matches surrounded by word boundaries. -This is equivalent to putting \\b before and after the search pattern. -.RS -.RE -.TP -.B \-x, \-\-line\-regexp -Only show matches surrounded by line boundaries. -This is equivalent to putting ^...$ around the search pattern. -.RS -.RE -.TP -.B \-z, \-\-search\-zip -Search in compressed files. -Currently gz, bz2, xz and lzma formats are supported. -.RS -.PP -Note that ripgrep expects to find the decompression binaries for the -respective formats in your system\[aq]s PATH for use with this flag. -.RE -.SH LESS COMMON OPTIONS -.TP -.B \-A, \-\-after\-context \f[I]NUM\f[] -Show NUM lines after each match. -.RS -.RE -.TP -.B \-B, \-\-before\-context \f[I]NUM\f[] -Show NUM lines before each match. -.RS -.RE -.TP -.B \-C, \-\-context \f[I]NUM\f[] -Show NUM lines before and after each match. -.RS -.RE -.TP -.B \-\-colors \f[I]SPEC\f[] ... -This flag specifies color settings for use in the output. -This flag may be provided multiple times. -Settings are applied iteratively. -Colors are limited to one of eight choices: red, blue, green, cyan, -magenta, yellow, white and black. -Styles are limited to nobold, bold, nointense or intense. -.RS -.PP -The format of the flag is {type}:{attribute}:{value}. -{type} should be one of path, line, column or match. -{attribute} can be fg, bg or style. -Value is either a color (for fg and bg) or a text style. -A special format, {type}:none, will clear all color settings for {type}. -.PP -For example, the following command will change the match color to -magenta and the background color for line numbers to yellow: -.IP -.nf -\f[C] -rg\ \-\-colors\ \[aq]match:fg:magenta\[aq]\ \-\-colors\ \[aq]line:bg:yellow\[aq]\ foo. -\f[] -.fi -.RE -.TP -.B \-\-column -Show column numbers (1 based) in output. -This only shows the column numbers for the first match on each line. -Note that this doesn\[aq]t try to account for Unicode. -One byte is equal to one column. -This implies \-\-line\-number. -.RS -.RE -.TP -.B \-\-context\-separator \f[I]SEPARATOR\f[] -The string to use when separating non\-continuous context lines. -Escape sequences may be used. -[default: \-\-] -.RS -.RE -.TP -.B \-\-debug -Show debug messages. -.RS -.RE -.TP -.B \-E, \-\-encoding \f[I]ENCODING\f[] -Specify the text encoding that ripgrep will use on all files searched. -The default value is \[aq]auto\[aq], which will cause ripgrep to do a -best effort automatic detection of encoding on a per\-file basis. -Other supported values can be found in the list of labels here: -https://encoding.spec.whatwg.org/#concept\-encoding\-get -.RS -.RE -.TP -.B \-f, \-\-file \f[I]FILE\f[] ... -Search for patterns from the given file, with one pattern per line. -When this flag is used or multiple times or in combination with the -\-e/\-\-regexp flag, then all patterns provided are searched. -Empty pattern lines will match all input lines, and the newline is not -counted as part of the pattern. -.RS -.RE -.TP -.B \-\-files -Print each file that would be searched (but don\[aq]t search). -.RS -.PP -Combine with the \-g flag to return matched paths, for example: -.IP -.nf -\f[C] -rg\ \-g\ \[aq]*.foo\[aq]\ \-\-files -\f[] -.fi -.RE -.TP -.B \-l, \-\-files\-with\-matches -Only show path of each file with matches. -.RS -.RE -.TP -.B \-\-files\-without\-match -Only show path of each file with no matches. -.RS -.RE -.TP -.B \-H, \-\-with\-filename -Display the file name for matches. -This is the default when more than one file is searched. -If \-\-heading is enabled, the file name will be shown above clusters of -matches from each file; otherwise, the file name will be shown on each -match. -.RS -.RE -.TP -.B \-\-no\-filename -Never show the filename for a match. -This is the default when one file is searched. -.RS -.RE -.TP -.B \-\-heading -Show the file name above clusters of matches from each file instead of -showing the file name for every match. -This is the default mode at a tty. -.RS -.RE -.TP -.B \-\-no\-heading -Don\[aq]t group matches by each file. -If \-H/\-\-with\-filename is enabled, then file names will be shown for -every line matched. -This is the default mode when not at a tty. -.RS -.RE -.TP -.B \-\-hidden -Search hidden directories and files. -(Hidden directories and files are skipped by default.) -.RS -.RE -.TP -.B \-\-iglob \f[I]GLOB\f[] ... -Include or exclude files/directories case insensitively. -This always overrides any other ignore logic if there is a conflict, but -is otherwise applied in addition to ignore files (e.g., .gitignore or -\&.ignore). -Multiple glob flags may be used. -Globbing rules match .gitignore globs. -Precede a glob with a \[aq]!\[aq] to exclude it. -.RS -.RE -.TP -.B \-\-ignore\-file \f[I]FILE\f[] ... -Specify additional ignore files for filtering file paths. -Ignore files should be in the gitignore format and are matched relative -to the current working directory. -These ignore files have lower precedence than all other ignore files. -When specifying multiple ignore files, earlier files have lower -precedence than later files. -.RS -.RE -.TP -.B \-L, \-\-follow -Follow symlinks. -.RS -.RE -.TP -.B \-\-line\-number\-width \f[I]NUM\f[] -Specify a width for the displayed line number. -If number of digits in the line number is less than this number, it is -left padded with spaces. -Note: This setting has no effect if \-\-no\-line\-number is enabled. -.RS -.RE -.TP -.B \-M, \-\-max\-columns \f[I]NUM\f[] -Don\[aq]t print lines longer than this limit in bytes. -Longer lines are omitted, and only the number of matches in that line is -printed. -.RS -.RE -.TP -.B \-m, \-\-max\-count \f[I]NUM\f[] -Limit the number of matching lines per file searched to NUM. -.RS -.RE -.TP -.B \-\-max\-filesize \f[I]NUM\f[]+\f[I]SUFFIX\f[]? -Ignore files larger than \f[I]NUM\f[] in size. -Directories will never be ignored. -.RS -.PP -\f[I]SUFFIX\f[] is optional and may be one of K, M or G. -These correspond to kilobytes, megabytes and gigabytes respectively. -If omitted the input is treated as bytes. -.RE -.TP -.B \-\-maxdepth \f[I]NUM\f[] -Descend at most NUM directories below the command line arguments. -A value of zero searches only the starting\-points themselves. -.RS -.RE -.TP -.B \-\-mmap -Search using memory maps when possible. -This is enabled by default when ripgrep thinks it will be faster. -(Note that mmap searching doesn\[aq]t currently support the various -context related options.) -.RS -.RE -.TP -.B \-\-no\-config -Never read configuration files. -When this flag is present, ripgrep will not respect the -RIPGREP_CONFIG_PATH environment variable. -.RS -.PP -If ripgrep ever grows a feature to automatically read configuration -files in pre\-defined locations, then this flag will also disable that -behavior as well. -.RE -.TP -.B \-\-no\-messages -Suppress all error messages. -.RS -.RE -.TP -.B \-\-no\-mmap -Never use memory maps, even when they might be faster. -.RS -.RE -.TP -.B \-\-no\-ignore -Don\[aq]t respect ignore files (.gitignore, .ignore, etc.) This implies -\-\-no\-ignore\-parent. -.RS -.RE -.TP -.B \-\-no\-ignore\-parent -Don\[aq]t respect ignore files in parent directories. -.RS -.RE -.TP -.B \-\-no\-ignore\-vcs -Don\[aq]t respect version control ignore files (e.g., .gitignore). -Note that .ignore files will continue to be respected. -.RS -.RE -.TP -.B \-0, \-\-null -Whenever a file name is printed, follow it with a NUL byte. -This includes printing filenames before matches, and when printing a -list of matching files such as with \-\-count, \-\-files\-with\-matches -and \-\-files. -.RS -.RE -.TP -.B \-o, \-\-only\-matching -Print only the matched (non\-empty) parts of a matching line, with each -such part on a separate output line. -.RS -.RE -.TP -.B \-\-passthru, \-\-passthrough -Show both matching and non\-matching lines. -This option cannot be used with \-\-only\-matching or \-\-replace. -.RS -.RE -.TP -.B \-\-path\-separator \f[I]SEPARATOR\f[] -The path separator to use when printing file paths. -This defaults to your platform\[aq]s path separator, which is / on Unix -and \\ on Windows. -This flag is intended for overriding the default when the environment -demands it (e.g., cygwin). -A path separator is limited to a single byte. -.RS -.RE -.TP -.B \-p, \-\-pretty -Alias for \-\-color=always \-\-heading \-\-line\-number. -.RS -.RE -.TP -.B \-r, \-\-replace \f[I]ARG\f[] -Replace every match with the string given when printing search results. -Neither this flag nor any other flag will modify your files. -.RS -.PP -Capture group indices (e.g., $5) and names (e.g., $foo) are supported in -the replacement string. -.PP -Note that the replacement by default replaces each match, and NOT the -entire line. -To replace the entire line, you should match the entire line. -For example, to emit only the first phone numbers in each line: -.IP -.nf -\f[C] -rg\ \[aq]^.*([0\-9]{3}\-[0\-9]{3}\-[0\-9]{4}).*$\[aq]\ \-\-replace\ \[aq]$1\[aq] -\f[] -.fi -.RE -.TP -.B \-s, \-\-case\-sensitive -Search case sensitively (default). -Overrides \-\-ignore\-case and \-\-smart\-case. -.RS -.RE -.TP -.B \-S, \-\-smart\-case -Search case insensitively if the pattern is all lowercase. -Search case sensitively otherwise. -This is overridden by either \-\-case\-sensitive or \-\-ignore\-case. -Note: This feature is smart enough to treat simple classes like \\S as -lowercase, but may not handle more complex syntax like \\p{Ll} as -expected. -.RS -.RE -.TP -.B \-\-sort\-files -Sort results by file path. -Note that this currently disables all parallelism and runs search in a -single thread. -.RS -.RE -.TP -.B \-j, \-\-threads \f[I]ARG\f[] -The number of threads to use. -0 means use the number of logical CPUs (capped at 12). -[default: 0] -.RS -.RE -.TP -.B \-\-version -Show the version number of ripgrep and exit. -.RS -.RE -.TP -.B \-\-vimgrep -Show results with every match on its own line, including line numbers -and column numbers. -With this option, a line with more than one match will be printed more -than once. -.RS -.PP -Recommended .vimrc configuration: -.IP -.nf -\f[C] -\ \ set\ grepprg=rg\\\ \-\-vimgrep -\ \ set\ grepformat^=%f:%l:%c:%m -\f[] -.fi -.PP -Use :grep to grep for something, then :cn and :cp to navigate through -the matches. -.RE -.SH FILE TYPE MANAGEMENT OPTIONS -.TP -.B \-\-type\-list -Show all supported file types and their associated globs. -.RS -.RE -.TP -.B \-\-type\-add \f[I]ARG\f[] ... -Add a new glob for a particular file type. -Only one glob can be added at a time. -Multiple \-\-type\-add flags can be provided. -Unless \-\-type\-clear is used, globs are added to any existing globs -inside of ripgrep. -Note that this must be passed to every invocation of rg. -Type settings are NOT persisted. -Example: -.RS -.IP -.nf -\f[C] -\ \ rg\ \-\-type\-add\ \[aq]foo:*.foo\[aq]\ \-tfoo\ PATTERN -\f[] -.fi -.PP -\-\-type\-add can also be used to include rules from other types with -the special include directive. -The include directive permits specifying one or more other type names -(separated by a comma) that have been defined and its rules will -automatically be imported into the type specified. -For example, to create a type called src that matches C++, Python and -Markdown files, one can use: -.IP -.nf -\f[C] -\ \ \-\-type\-add\ \[aq]src:include:cpp,py,md\[aq] -\f[] -.fi -.PP -Additional glob rules can still be added to the src type by using the -\-\-type\-add flag again: -.IP -.nf -\f[C] -\ \ \-\-type\-add\ \[aq]src:include:cpp,py,md\[aq]\ \-\-type\-add\ \[aq]src:*.foo\[aq] -\f[] -.fi -.PP -Note that type names must consist only of Unicode letters or numbers. -Punctuation characters are not allowed. -.RE -.TP -.B \-\-type\-clear \f[I]TYPE\f[] ... -Clear the file type globs previously defined for TYPE. -This only clears the default type definitions that are found inside of -ripgrep. -Note that this must be passed to every invocation of rg. -.RS -.RE -.SH CONFIGURATION FILES -.PP -ripgrep supports reading configuration files that change ripgrep\[aq]s -default behavior. -The format of the configuration file is an "rc" style and is very -simple. -It is defined by two rules: -.IP -.nf -\f[C] -1.\ Every\ line\ is\ a\ shell\ argument,\ after\ trimming\ ASCII\ whitespace. -2.\ Lines\ starting\ with\ \[aq]#\[aq]\ (optionally\ preceded\ by\ any\ amount\ of -\ \ \ ASCII\ whitespace)\ are\ ignored. -\f[] -.fi -.PP -ripgrep will look for a single configuration file if and only if the -RIPGREP_CONFIG_PATH environment variable is set and is non\-empty. -ripgrep will parse shell arguments from this file on startup and will -behave as if the arguments in this file were prepended to any explicit -arguments given to ripgrep on the command line. -.PP -For example, if your ripgreprc file contained a single line: -.IP -.nf -\f[C] -\-\-smart\-case -\f[] -.fi -.PP -then the following command -.IP -.nf -\f[C] -RIPGREP_CONFIG_PATH=wherever/.ripgreprc\ rg\ foo -\f[] -.fi -.PP -would behave identically to the following command -.IP -.nf -\f[C] -rg\ \-\-smart\-case\ foo -\f[] -.fi -.PP -ripgrep also provides a flag, \-\-no\-config, that when present will -suppress any and all support for configuration. -This includes any future support for auto\-loading configuration files -from pre\-determined paths. -.PP -Conflicts between configuration files and explicit arguments are handled -exactly like conflicts in the same command line invocation. -That is, this command: -.IP -.nf -\f[C] -RIPGREP_CONFIG_PATH=wherever/.ripgreprc\ rg\ foo\ \-\-case\-sensitive -\f[] -.fi -.PP -is exactly equivalent to -.IP -.nf -\f[C] -rg\ \-\-smart\-case\ foo\ \-\-case\-sensitive -\f[] -.fi -.PP -in which case, the \-\-case\-sensitive flag would override the -\-\-smart\-case flag. -.SH SHELL COMPLETION -.PP -Shell completion files are included in the release tarball for Bash, -Fish, Zsh and PowerShell. -.PP -For \f[B]bash\f[], move \f[C]rg.bash\-completion\f[] to -\f[C]$XDG_CONFIG_HOME/bash_completion\f[] or -\f[C]/etc/bash_completion.d/\f[]. -.PP -For \f[B]fish\f[], move \f[C]rg.fish\f[] to -\f[C]$HOME/.config/fish/completions\f[]. diff --git a/doc/rg.1.md b/doc/rg.1.md deleted file mode 100644 index c92c6aa3..00000000 --- a/doc/rg.1.md +++ /dev/null @@ -1,456 +0,0 @@ -# NAME - -rg - recursively search current directory for lines matching a pattern - -# SYNOPSIS - -rg [*OPTIONS*] *PATTERN* [*PATH* ...] - -rg [*OPTIONS*] [-e *PATTERN* ...] [-f *FILE* ...] [*PATH* ...] - -rg [*OPTIONS*] --files [*PATH* ...] - -rg [*OPTIONS*] --type-list - -rg [*OPTIONS*] --help - -rg [*OPTIONS*] --version - -# DESCRIPTION - -ripgrep (rg) combines the usability of The Silver Searcher (an ack clone) with -the raw speed of grep. - -ripgrep's regex engine uses finite automata and guarantees linear time -searching. Because of this, features like backreferences and arbitrary -lookaround are not supported. - -Note that ripgrep may abort unexpectedly when using default settings if it -searches a file that is simultaneously truncated. This behavior can be avoided -by passing the --no-mmap flag. - -Project home page: https://github.com/BurntSushi/ripgrep - -# POSITIONAL ARGUMENTS - -*PATTERN* -: A regular expression used for searching. To match a pattern beginning with a - dash, use the -e/--regexp option. - -*PATH* -: A file or directory to search. Directories are searched recursively. Paths - specified expicitly on the command line override glob and ignore rules. - -# COMMON OPTIONS - --a, --text -: Search binary files as if they were text. - --c, --count -: Only show count of line matches for each file. - ---color *WHEN* -: Whether to use color in the output. Valid values are never, auto, always or - ansi. The default is auto. When always is used, coloring is attempted based - on your environment. When ansi is used, coloring is forcefully done using - ANSI escape color codes. - --e, --regexp *PATTERN* ... -: Use PATTERN to search. This option can be provided multiple times, where all - patterns given are searched. This is also useful when searching for patterns - that start with a dash. - --F, --fixed-strings -: Treat the pattern as a literal string instead of a regular expression. - --g, --glob *GLOB* ... -: Include or exclude files for searching that match the given glob. This always - overrides any other ignore logic if there is a conflict, but is otherwise - applied in addition to ignore files (e.g., .gitignore or .ignore). Multiple - glob flags may be used. Globbing rules match .gitignore globs. Precede a - glob with a '!' to exclude it. - - The --glob flag subsumes the functionality of both the --include and - --exclude flags commonly found in other tools. - - Values given to -g must be quoted or your shell will expand them and result - in unexpected behavior. - - Combine with the --files flag to return matched filenames - (i.e., to replicate ack/ag's -g flag). For example: - - rg -g '*.foo' --files - --h, --help -: Show this usage message. - --i, --ignore-case -: Case insensitive search. Overridden by --case-sensitive. - --n, --line-number -: Show line numbers (1-based). This is enabled by default at a tty. - --N, --no-line-number -: Suppress line numbers. - --q, --quiet -: Do not print anything to stdout. If a match is found in a file, stop - searching that file. - --t, --type *TYPE* ... -: Only search files matching TYPE. Multiple type flags may be provided. Use the - --type-list flag to list all available types. - --T, --type-not *TYPE* ... -: Do not search files matching TYPE. Multiple not-type flags may be provided. - --u, --unrestricted ... -: Reduce the level of 'smart' searching. A single -u doesn't respect .gitignore - (etc.) files. Two -u flags will search hidden files and directories. Three - -u flags will search binary files. -uu is equivalent to `grep -r`, and -uuu - is equivalent to `grep -a -r`. - - Note that the -u flags are convenient aliases for other combinations of - flags. -u aliases --no-ignore. -uu aliases --no-ignore --hidden. - -uuu aliases --no-ignore --hidden --text. - --v, --invert-match -: Invert matching. - --w, --word-regexp -: Only show matches surrounded by word boundaries. This is equivalent to - putting \\b before and after the search pattern. - --x, --line-regexp -: Only show matches surrounded by line boundaries. This is equivalent to - putting ^...$ around the search pattern. - --z, --search-zip -: Search in compressed files. Currently gz, bz2, xz and lzma - formats are supported. - - Note that ripgrep expects to find the decompression binaries for the - respective formats in your system's PATH for use with this flag. - -# LESS COMMON OPTIONS - --A, --after-context *NUM* -: Show NUM lines after each match. - --B, --before-context *NUM* -: Show NUM lines before each match. - --C, --context *NUM* -: Show NUM lines before and after each match. - ---colors *SPEC* ... -: This flag specifies color settings for use in the output. This flag may be - provided multiple times. Settings are applied iteratively. Colors are limited - to one of eight choices: red, blue, green, cyan, magenta, yellow, white and - black. Styles are limited to nobold, bold, nointense or intense. - - The format of the flag is {type}:{attribute}:{value}. {type} should be one - of path, line, column or match. {attribute} can be fg, bg or style. Value - is either a color (for fg and bg) or a text style. A special format, - {type}:none, will clear all color settings for {type}. - - For example, the following command will change the match color to magenta - and the background color for line numbers to yellow: - - rg --colors 'match:fg:magenta' --colors 'line:bg:yellow' foo. - ---column -: Show column numbers (1 based) in output. This only shows the column - numbers for the first match on each line. Note that this doesn't try - to account for Unicode. One byte is equal to one column. This implies - --line-number. - ---context-separator *SEPARATOR* -: The string to use when separating non-continuous context lines. Escape - sequences may be used. [default: --] - ---debug -: Show debug messages. - --E, --encoding *ENCODING* -: Specify the text encoding that ripgrep will use on all files - searched. The default value is 'auto', which will cause ripgrep to do - a best effort automatic detection of encoding on a per-file basis. - Other supported values can be found in the list of labels here: - https://encoding.spec.whatwg.org/#concept-encoding-get - --f, --file *FILE* ... -: Search for patterns from the given file, with one pattern per line. When this - flag is used or multiple times or in combination with the -e/--regexp flag, - then all patterns provided are searched. Empty pattern lines will match all - input lines, and the newline is not counted as part of the pattern. - ---files -: Print each file that would be searched (but don't search). - - Combine with the -g flag to return matched paths, for example: - - rg -g '*.foo' --files - --l, --files-with-matches -: Only show path of each file with matches. - ---files-without-match -: Only show path of each file with no matches. - --H, --with-filename -: Display the file name for matches. This is the default when - more than one file is searched. If --heading is enabled, the - file name will be shown above clusters of matches from each - file; otherwise, the file name will be shown on each match. - ---no-filename -: Never show the filename for a match. This is the default when - one file is searched. - ---heading -: Show the file name above clusters of matches from each file instead of - showing the file name for every match. This is the default mode at a tty. - ---no-heading -: Don't group matches by each file. If -H/--with-filename is enabled, then - file names will be shown for every line matched. This is the default mode - when not at a tty. - ---hidden -: Search hidden directories and files. (Hidden directories and files are - skipped by default.) - ---iglob *GLOB* ... -: Include or exclude files/directories case insensitively. This always - overrides any other ignore logic if there is a conflict, but is otherwise - applied in addition to ignore files (e.g., .gitignore or .ignore). Multiple - glob flags may be used. Globbing rules match .gitignore globs. Precede a - glob with a '!' to exclude it. - ---ignore-file *FILE* ... -: Specify additional ignore files for filtering file paths. - Ignore files should be in the gitignore format and are matched - relative to the current working directory. These ignore files - have lower precedence than all other ignore files. When - specifying multiple ignore files, earlier files have lower - precedence than later files. - --L, --follow -: Follow symlinks. - ---line-number-width *NUM* -: Specify a width for the displayed line number. If number of digits - in the line number is less than this number, it is left padded with - spaces. Note: This setting has no effect if --no-line-number is - enabled. - --M, --max-columns *NUM* -: Don't print lines longer than this limit in bytes. Longer lines are omitted, - and only the number of matches in that line is printed. - --m, --max-count *NUM* -: Limit the number of matching lines per file searched to NUM. - ---max-filesize *NUM*+*SUFFIX*? -: Ignore files larger than *NUM* in size. Directories will never be ignored. - - *SUFFIX* is optional and may be one of K, M or G. These correspond to - kilobytes, megabytes and gigabytes respectively. If omitted the input is - treated as bytes. - ---maxdepth *NUM* -: Descend at most NUM directories below the command line arguments. - A value of zero searches only the starting-points themselves. - ---mmap -: Search using memory maps when possible. This is enabled by default - when ripgrep thinks it will be faster. (Note that mmap searching - doesn't currently support the various context related options.) - ---no-config -: Never read configuration files. When this flag is present, ripgrep will not - respect the RIPGREP_CONFIG_PATH environment variable. - - If ripgrep ever grows a feature to automatically read configuration files - in pre-defined locations, then this flag will also disable that behavior as - well. - ---no-messages -: Suppress all error messages. - ---no-mmap -: Never use memory maps, even when they might be faster. - ---no-ignore -: Don't respect ignore files (.gitignore, .ignore, etc.) - This implies --no-ignore-parent. - ---no-ignore-parent -: Don't respect ignore files in parent directories. - ---no-ignore-vcs -: Don't respect version control ignore files (e.g., .gitignore). - Note that .ignore files will continue to be respected. - --0, --null -: Whenever a file name is printed, follow it with a NUL byte. - This includes printing filenames before matches, and when printing - a list of matching files such as with --count, --files-with-matches - and --files. - --o, --only-matching -: Print only the matched (non-empty) parts of a matching line, with each such - part on a separate output line. - ---passthru, --passthrough -: Show both matching and non-matching lines. This option cannot be used with - --only-matching or --replace. - ---path-separator *SEPARATOR* -: The path separator to use when printing file paths. This defaults to your - platform's path separator, which is / on Unix and \\ on Windows. This flag is - intended for overriding the default when the environment demands it (e.g., - cygwin). A path separator is limited to a single byte. - --p, --pretty -: Alias for --color=always --heading --line-number. - --r, --replace *ARG* -: Replace every match with the string given when printing search results. - Neither this flag nor any other flag will modify your files. - - Capture group indices (e.g., $5) and names (e.g., $foo) are supported - in the replacement string. - - Note that the replacement by default replaces each match, and NOT the - entire line. To replace the entire line, you should match the entire line. - For example, to emit only the first phone numbers in each line: - - rg '^.*([0-9]{3}-[0-9]{3}-[0-9]{4}).*$' --replace '$1' - --s, --case-sensitive -: Search case sensitively (default). Overrides --ignore-case and --smart-case. - --S, --smart-case -: Search case insensitively if the pattern is all lowercase. - Search case sensitively otherwise. This is overridden by either - --case-sensitive or --ignore-case. Note: This feature is smart enough - to treat simple classes like \\S as lowercase, but may not handle more - complex syntax like \\p{Ll} as expected. - ---sort-files -: Sort results by file path. Note that this currently - disables all parallelism and runs search in a single thread. - --j, --threads *ARG* -: The number of threads to use. 0 means use the number of logical CPUs - (capped at 12). [default: 0] - ---version -: Show the version number of ripgrep and exit. - ---vimgrep -: Show results with every match on its own line, including - line numbers and column numbers. With this option, a line with - more than one match will be printed more than once. - - Recommended .vimrc configuration: - - set grepprg=rg\ --vimgrep - set grepformat^=%f:%l:%c:%m - - Use :grep to grep for something, then :cn and :cp to navigate through the - matches. - -# FILE TYPE MANAGEMENT OPTIONS - ---type-list -: Show all supported file types and their associated globs. - ---type-add *ARG* ... -: Add a new glob for a particular file type. Only one glob can be added - at a time. Multiple --type-add flags can be provided. Unless --type-clear - is used, globs are added to any existing globs inside of ripgrep. Note that - this must be passed to every invocation of rg. Type settings are NOT - persisted. Example: - - rg --type-add 'foo:*.foo' -tfoo PATTERN - - --type-add can also be used to include rules from other types - with the special include directive. The include directive - permits specifying one or more other type names (separated by a - comma) that have been defined and its rules will automatically - be imported into the type specified. For example, to create a - type called src that matches C++, Python and Markdown files, one - can use: - - --type-add 'src:include:cpp,py,md' - - Additional glob rules can still be added to the src type by - using the --type-add flag again: - - --type-add 'src:include:cpp,py,md' --type-add 'src:*.foo' - - Note that type names must consist only of Unicode letters or - numbers. Punctuation characters are not allowed. - ---type-clear *TYPE* ... -: Clear the file type globs previously defined for TYPE. This only clears - the default type definitions that are found inside of ripgrep. Note - that this must be passed to every invocation of rg. - -# CONFIGURATION FILES - -ripgrep supports reading configuration files that change -ripgrep's default behavior. The format of the configuration file is an -"rc" style and is very simple. It is defined by two rules: - - 1. Every line is a shell argument, after trimming ASCII whitespace. - 2. Lines starting with '#' (optionally preceded by any amount of - ASCII whitespace) are ignored. - -ripgrep will look for a single configuration file if and only if the -RIPGREP_CONFIG_PATH environment variable is set and is non-empty. -ripgrep will parse shell arguments from this file on startup and will -behave as if the arguments in this file were prepended to any explicit -arguments given to ripgrep on the command line. - -For example, if your ripgreprc file contained a single line: - - --smart-case - -then the following command - - RIPGREP_CONFIG_PATH=wherever/.ripgreprc rg foo - -would behave identically to the following command - - rg --smart-case foo - -ripgrep also provides a flag, --no-config, that when present will suppress -any and all support for configuration. This includes any future support -for auto-loading configuration files from pre-determined paths. - -Conflicts between configuration files and explicit arguments are handled -exactly like conflicts in the same command line invocation. That is, -this command: - - RIPGREP_CONFIG_PATH=wherever/.ripgreprc rg foo --case-sensitive - -is exactly equivalent to - - rg --smart-case foo --case-sensitive - -in which case, the --case-sensitive flag would override the --smart-case -flag. - -# SHELL COMPLETION - -Shell completion files are included in the release tarball for Bash, Fish, Zsh -and PowerShell. - -For **bash**, move `rg.bash-completion` to `$XDG_CONFIG_HOME/bash_completion` -or `/etc/bash_completion.d/`. - -For **fish**, move `rg.fish` to `$HOME/.config/fish/completions`. diff --git a/doc/rg.1.txt.tpl b/doc/rg.1.txt.tpl new file mode 100644 index 00000000..a1068c09 --- /dev/null +++ b/doc/rg.1.txt.tpl @@ -0,0 +1,136 @@ +rg(1) +===== + +Name +---- +rg - recursively search current directory for lines matching a pattern + + +Synopsis +-------- +*rg* [_OPTIONS_] _PATTERN_ [_PATH_...] + +*rg* [_OPTIONS_] [*-e* _PATTERN_...] [*-f* _PATH_...] [_PATH_...] + +*rg* [_OPTIONS_] *--files* [_PATH_...] + +*rg* [_OPTIONS_] *--type-list* + +*rg* [_OPTIONS_] *--help* + +*rg* [_OPTIONS_] *--version* + + +DESCRIPTION +----------- +ripgrep (rg) recursively searches your current directory for a regex pattern. +By default, ripgrep will respect your `.gitignore` and automatically skip +hidden files/directories and binary files. + +ripgrep's regex engine uses finite automata and guarantees linear time +searching. Because of this, features like backreferences and arbitrary +lookaround are not supported. + + +POSITIONAL ARGUMENTS +-------------------- +_PATTERN_:: + A regular expression used for searching. To match a pattern beginning with a + dash, use the -e/--regexp option. + +_PATH_:: + A file or directory to search. Directories are searched recursively. Paths + specified expicitly on the command line override glob and ignore rules. + + +OPTIONS +------- +{OPTIONS} + + +EXIT STATUS +----------- +If ripgrep finds a match, then the exit status of the program is 0. If no match +could be found, then the exit status is non-zero. + + +CONFIGURATION FILES +------------------- +ripgrep supports reading configuration files that change ripgrep's default +behavior. The format of the configuration file is an "rc" style and is very +simple. It is defined by two rules: + + 1. Every line is a shell argument, after trimming ASCII whitespace. + 2. Lines starting with _#_ (optionally preceded by any amount of + ASCII whitespace) are ignored. + +ripgrep will look for a single configuration file if and only if the +_RIPGREP_CONFIG_PATH_ environment variable is set and is non-empty. +ripgrep will parse shell arguments from this file on startup and will +behave as if the arguments in this file were prepended to any explicit +arguments given to ripgrep on the command line. + +For example, if your ripgreprc file contained a single line: + + --smart-case + +then the following command + + RIPGREP_CONFIG_PATH=wherever/.ripgreprc rg foo + +would behave identically to the following command + + rg --smart-case foo + +ripgrep also provides a flag, *--no-config*, that when present will suppress +any and all support for configuration. This includes any future support +for auto-loading configuration files from pre-determined paths. + +Conflicts between configuration files and explicit arguments are handled +exactly like conflicts in the same command line invocation. That is, +this command: + + RIPGREP_CONFIG_PATH=wherever/.ripgreprc rg foo --case-sensitive + +is exactly equivalent to + + rg --smart-case foo --case-sensitive + +in which case, the *--case-sensitive* flag would override the *--smart-case* +flag. + + +SHELL COMPLETION +---------------- +Shell completion files are included in the release tarball for Bash, Fish, Zsh +and PowerShell. + +For *bash*, move `rg.bash-completion` to `$XDG_CONFIG_HOME/bash_completion` +or `/etc/bash_completion.d/`. + +For *fish*, move `rg.fish` to `$HOME/.config/fish/completions`. + + +CAVEATS +------- +ripgrep may abort unexpectedly when using default settings if it searches a +file that is simultaneously truncated. This behavior can be avoided by passing +the --no-mmap flag which will forcefully disable the use of memory maps in all +cases. + + +VERSION +------- +{VERSION} + + +HOMEPAGE +-------- +https://github.com/BurntSushi/ripgrep + +Please report bugs and feature requests in the issue tracker. + + +AUTHORS +------- +Andrew Gallant diff --git a/src/app.rs b/src/app.rs index 3591dc22..c05fd01b 100644 --- a/src/app.rs +++ b/src/app.rs @@ -57,7 +57,7 @@ pub fn app() -> App<'static, 'static> { // 'static, but we need to build the version string dynamically. We can // fake the 'static lifetime with lazy_static. lazy_static! { - static ref LONG_VERSION: String = long_version(); + static ref LONG_VERSION: String = long_version(None); } let mut app = App::new("ripgrep") @@ -78,7 +78,11 @@ pub fn app() -> App<'static, 'static> { } /// Return the "long" format of ripgrep's version string. -fn long_version() -> String { +/// +/// If a revision hash is given, then it is used. If one isn't given, then +/// the RIPGREP_BUILD_GIT_HASH env var is inspect for it. If that isn't set, +/// then a revision hash is not included in the version string returned. +pub fn long_version(revision_hash: Option<&str>) -> String { // Let's say whether faster CPU instructions are enabled or not. let mut features = vec![]; if cfg!(feature = "simd-accel") { @@ -93,7 +97,7 @@ fn long_version() -> String { } // Do we have a git hash? // (Yes, if ripgrep was built on a machine with `git` installed.) - let hash = match option_env!("RIPGREP_BUILD_GIT_HASH") { + let hash = match revision_hash.or(option_env!("RIPGREP_BUILD_GIT_HASH")) { None => String::new(), Some(githash) => format!(" (rev {})", githash), }; @@ -113,26 +117,26 @@ type Arg = clap::Arg<'static, 'static>; /// use of clap. #[allow(dead_code)] #[derive(Clone)] -struct RGArg { +pub struct RGArg { /// The underlying clap argument. claparg: Arg, /// The name of this argument. This is always present and is the name /// used in the code to find the value of an argument at runtime. - name: &'static str, + pub name: &'static str, /// A short documentation string describing this argument. This string /// should fit on a single line and be a complete sentence. /// /// This is shown in the `-h` output. - doc_short: &'static str, + pub doc_short: &'static str, /// A longer documentation string describing this argument. This usually /// starts with the contents of `doc_short`. This is also usually many /// lines, potentially paragraphs, and may contain examples and additional /// prose. /// /// This is shown in the `--help` output. - doc_long: &'static str, + pub doc_long: &'static str, /// The type of this argument. - kind: RGArgKind, + pub kind: RGArgKind, } /// The kind of a ripgrep argument. @@ -149,7 +153,7 @@ struct RGArg { /// why; the state we do capture is motivated by use cases (like generating /// documentation). #[derive(Clone)] -enum RGArgKind { +pub enum RGArgKind { /// A positional argument. Positional { /// The name of the value used in the `-h/--help` output. By @@ -476,7 +480,8 @@ macro_rules! long { ($lit:expr) => { concat!($lit, " ") } } -fn all_args_and_flags() -> Vec { +/// Generate a sequence of all positional and flag arguments. +pub fn all_args_and_flags() -> Vec { let mut args = vec![]; // The positional arguments must be defined first and in order. arg_pattern(&mut args); -- cgit v1.2.3