From b1e4e62fab9263602e882f6dadaf5448be16ce9e Mon Sep 17 00:00:00 2001 From: John Kerl Date: Sun, 1 Nov 2015 21:49:49 -0500 Subject: [PATCH] internally split out main-usage functions for manpage-autogen support --- c/cli/mlrcli.c | 72 +++++++++++--- c/mapping/mapper_cut.c | 2 +- doc/mkman.rb | 219 +++-------------------------------------- 3 files changed, 76 insertions(+), 217 deletions(-) diff --git a/c/cli/mlrcli.c b/c/cli/mlrcli.c index d73a22075..02c97df46 100644 --- a/c/cli/mlrcli.c +++ b/c/cli/mlrcli.c @@ -178,6 +178,19 @@ static char* rebackslash(char* sep) { #define DEFAULT_OQUOTING QUOTE_MINIMAL // ---------------------------------------------------------------- +// The main_usage() function is split out into subroutines in support of the +// manpage autogenerator. + +static void main_usage_synopsis(FILE* o, char* argv0) { + fprintf(o, "Usage: %s [I/O options] {verb} [verb-dependent options ...] {zero or more file names}\n", argv0); +} + +static void list_all_verbs_raw(FILE* o) { + for (int i = 0; i < mapper_lookup_table_length; i++) { + fprintf(o, "%s\n", mapper_lookup_table[i]->verb); + } +} + static void list_all_verbs(FILE* o) { char* leader = " "; char* separator = " "; @@ -203,29 +216,21 @@ static void list_all_verbs(FILE* o) { fprintf(o, "\n"); } -static void list_all_verbs_raw(FILE* o) { - for (int i = 0; i < mapper_lookup_table_length; i++) { - fprintf(o, "%s\n", mapper_lookup_table[i]->verb); - } -} - -static void main_usage(FILE* o, char* argv0) { - fprintf(o, "Usage: %s [I/O options] {verb} [verb-dependent options ...] {file names}\n", argv0); - list_all_verbs(o); - - fprintf(o, "Example: %s --csv --rs lf --fs tab cut -f hostname,uptime file1.csv file2.csv\n", argv0); +static void main_usage_help_options(FILE* o, char* argv0) { fprintf(o, "Please use \"%s -h\" or \"%s --help\" to show this message.\n", argv0, argv0); fprintf(o, "Please use \"%s --version\" to show the software version.\n", argv0); fprintf(o, "Please use \"%s {verb name} --help\" for verb-specific help.\n", argv0); fprintf(o, "Please use \"%s --list-all-verbs\" to list only verb names.\n", argv0); fprintf(o, "Please use \"%s --help-all-verbs\" for help on all verbs.\n", argv0); +} - fprintf(o, "\n"); +static void main_usage_functions(FILE* o, char* argv0) { lrec_evaluator_list_functions(o); fprintf(o, "Please use \"%s --help-function {function name}\" for function-specific help.\n", argv0); fprintf(o, "Please use \"%s --help-all-functions\" or \"%s -f\" for help on all functions.\n", argv0, argv0); - fprintf(o, "\n"); +} +static void main_usage_data_format_options(FILE* o, char* argv0) { fprintf(o, "Data-format options, for input, output, or both:\n"); fprintf(o, " --idkvp --odkvp --dkvp Delimited key-value pairs, e.g \"a=1,b=2\"\n"); fprintf(o, " (default)\n"); @@ -239,6 +244,9 @@ static void main_usage(FILE* o, char* argv0) { fprintf(o, " -p is a keystroke-saver for --nidx --fs space --repifs\n"); fprintf(o, " Examples: --csv for CSV-formatted input and output; --idkvp --opprint for\n"); fprintf(o, " DKVP-formatted input and pretty-printed output.\n"); +} + +static void main_usage_separator_options(FILE* o, char* argv0) { fprintf(o, "Separator options, for input, output, or both:\n"); fprintf(o, " --rs --irs --ors Record separators, e.g. 'lf' or '\\r\\n'\n"); fprintf(o, " --fs --ifs --ofs --repifs Field separators, e.g. comma\n"); @@ -284,10 +292,16 @@ static void main_usage(FILE* o, char* argv0) { char* ps = lhmss_get(default_pses, filefmt); fprintf(o, " %-12s %-8s %-8s %s\n", filefmt, rebackslash(rs), rebackslash(fs), rebackslash(ps)); } +} + +static void main_usage_csv_options(FILE* o, char* argv0) { fprintf(o, "Relevant to CSV/CSV-lite input only:\n"); fprintf(o, " --implicit-csv-header Use 1,2,3,... as field labels, rather than from line 1\n"); fprintf(o, " of input files. Tip: combine with \"label\" to recreate\n"); fprintf(o, " missing headers.\n"); +} + +static void main_usage_double_quoting(FILE* o, char* argv0) { fprintf(o, "Double-quoting for CSV output:\n"); fprintf(o, " --quote-all Wrap all fields in double quotes\n"); fprintf(o, " --quote-none Do not wrap any fields in double quotes, even if they have \n"); @@ -296,15 +310,27 @@ static void main_usage(FILE* o, char* argv0) { fprintf(o, " in them (default)\n"); fprintf(o, " --quote-numeric Wrap fields in double quotes only if they have numbers\n"); fprintf(o, " in them\n"); +} + +static void main_usage_numerical_formatting(FILE* o, char* argv0) { fprintf(o, "Numerical formatting:\n"); fprintf(o, " --ofmt {format} E.g. %%.18lf, %%.0lf. Please use sprintf-style codes for\n"); fprintf(o, " double-precision. Applies to verbs which compute new\n"); fprintf(o, " values, e.g. put, stats1, stats2. See also the fmtnum\n"); fprintf(o, " function within mlr put (mlr --help-all-functions).\n"); +} + +static void main_usage_other_options(FILE* o, char* argv0) { fprintf(o, "Other options:\n"); fprintf(o, " --seed {n} with n of the form 12345678 or 0xcafefeed. For put/filter urand().\n"); +} + +static void main_usage_then_chaining(FILE* o, char* argv0) { fprintf(o, "Output of one verb may be chained as input to another using \"then\", e.g.\n"); fprintf(o, " %s stats1 -a min,mean,max -f flag,u,v -g color then sort -f color\n", argv0); +} + +static void main_usage_see_also(FILE* o, char* argv0) { fprintf(o, "For more information please see http://johnkerl.org/miller/doc and/or\n"); fprintf(o, "http://github.com/johnkerl/miller."); #ifdef HAVE_CONFIG_H @@ -314,6 +340,26 @@ static void main_usage(FILE* o, char* argv0) { #endif // HAVE_CONFIG_H } +// ---------------------------------------------------------------- +static void main_usage(FILE* o, char* argv0) { + main_usage_synopsis(o, argv0); + list_all_verbs(o); + fprintf(o, "Example: %s --csv --rs lf --fs tab cut -f hostname,uptime file1.csv file2.csv\n", argv0); + main_usage_help_options(o, argv0); + fprintf(o, "\n"); + main_usage_functions(o, argv0); + fprintf(o, "\n"); + main_usage_data_format_options(o, argv0); + main_usage_separator_options(o, argv0); + main_usage_csv_options(o, argv0); + main_usage_double_quoting(o, argv0); + main_usage_numerical_formatting(o, argv0); + main_usage_other_options(o, argv0); + main_usage_then_chaining(o, argv0); + main_usage_see_also(o, argv0); +} + +// ---------------------------------------------------------------- static void usage_all_verbs(char* argv0) { char* separator = "================================================================"; diff --git a/c/mapping/mapper_cut.c b/c/mapping/mapper_cut.c index 89716772d..b0d3bc7e6 100644 --- a/c/mapping/mapper_cut.c +++ b/c/mapping/mapper_cut.c @@ -37,7 +37,7 @@ static void mapper_cut_usage(FILE* o, char* argv0, char* verb) { fprintf(o, "-f {a,b,c} Field names to include for cut.\n"); fprintf(o, "-o Retain fields in the order specified here in the argument list.\n"); fprintf(o, " Default is to retain them in the order found in the input data.\n"); - fprintf(o, "-x|--complement Exclude, rather that include, field names specified by -f.\n"); + fprintf(o, "-x|--complement Exclude, rather than include, field names specified by -f.\n"); fprintf(o, "-r Treat field names as regular expressions. \"ab\", \"a.*b\" will\n"); fprintf(o, " match any field name containing the substring \"ab\" or matching\n"); fprintf(o, " \"a.*b\", respectively; anchors of the form \"^ab$\", \"^a.*b$\" may\n"); diff --git a/doc/mkman.rb b/doc/mkman.rb index 765a9056e..bd6135294 100755 --- a/doc/mkman.rb +++ b/doc/mkman.rb @@ -1,5 +1,7 @@ #!/usr/bin/env ruby +# xxx note about why: mindeps + # ---------------------------------------------------------------- def main @@ -10,6 +12,10 @@ def main "Miller is like sed, awk, cut, join, and sort for name-indexed data such as CSV." ]) + print make_section('SYNOPSIS', [ +"mlr [I/O options] {verb} [verb-dependent options ...] {zero or more file names}" + ]) + print make_section('DESCRIPTION', [ """This is something the Unix toolkit always could have done, and arguably always should have done. It operates on key-value-pair data while the familiar @@ -45,16 +51,12 @@ separator, --ors the output record separator, and --rs sets both the input and output separator to the given value.""" ]) - print make_subsection('SEPARATOR', [ -"""asdfasdfadf""" - ]) - print make_code_block(`mlr -h`) # xxx do better than backtick -- trap $? verbs = `mlr --list-all-verbs-raw` print make_subsection('VERBS', [ -"""asdfasdfadf""" + "" ]) verbs = verbs.strip.split("\n") for verb in verbs @@ -91,7 +93,7 @@ end # ---------------------------------------------------------------- # xxx temp def make_subsection(title, paragraphs) - retval = ".SH \"#{title}\"\n" + retval = ".SS \"#{title}\"\n" paragraphs.each do |paragraph| retval += ".sp\n" retval += groff_encode(paragraph) + "\n" @@ -102,7 +104,8 @@ end # ---------------------------------------------------------------- # xxx temp def make_subsubsection(title, paragraphs) - retval = ".SH \"#{title}\"\n" + retval = ".sp\n"; + retval += "\\fB#{title}\\fR\n" paragraphs.each do |paragraph| retval += ".sp\n" retval += groff_encode(paragraph) + "\n" @@ -113,10 +116,10 @@ end # ---------------------------------------------------------------- def make_code_block(block) retval = ".if n \\{\\\n" - retval += ".RS 4\n" + retval += ".RS 0\n" retval += ".\\}\n" retval += ".nf\n" - retval += block + retval += block.gsub('\\', '\e') retval += ".fi\n" retval += ".if n \\{\\\n" retval += ".RE\n" @@ -124,203 +127,13 @@ end # ---------------------------------------------------------------- def groff_encode(line) - line = line.gsub(/'/, '\(cq') - line = line.gsub(/"/, '\(dq') + #line = line.gsub(/'/, '\(cq') + #line = line.gsub(/"/, '\(dq') line = line.gsub(/\./, '\&') - line = line.gsub(/-/, '\-') + #line = line.gsub(/-/, '\-') + line = line.gsub(/\\/, '\e') line end # ================================================================ main - -# ================================================================ - -# .TH "MILLER" "1" "09/14/2015" "\ \&" "\ \&" -# .\" ----------------------------------------------------------------- -# .\" * Define some portability stuff -# .\" ----------------------------------------------------------------- -# .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# .\" http://bugs.debian.org/507673 -# .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html -# .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# .ie \n(.g .ds Aq \(aq -# .el .ds Aq ' -# .\" ----------------------------------------------------------------- -# .\" * set default formatting -# .\" ----------------------------------------------------------------- -# .\" disable hyphenation -# .nh -# .\" disable justification (adjust text to left margin only) -# .ad l - -# .\" ----------------------------------------------------------------- -# .\" * MAIN CONTENT STARTS HERE * -# .\" ----------------------------------------------------------------- -# .SH "NAME" -# miller \- sed, awk, cut, join, and sort for name\-indexed data such as CSV - -# .\" ---------------------------------------------------------------- -# .SH "SYNOPSIS" -# .sp - -# .\" ---------------------------------------------------------------- -# .SH "DESCRIPTION" -# .sp -# Description text with backslash ampersand period\&. Also \-\- backslash dash. -# Also \(cq for single quote. -# Also \(dq for double quote. -# Also \*(Aq for single quote. - -# .\" ---------------------------------------------------------------- -# .SH "EXAMPLES" -# .sp -# .if n \{\ -# .RS 4 -# .\} -# .nf -# Here is a code block -# Here is a code block -# Here is a code block -# .fi -# .if n \{\ -# .RE -# .\} - -# .\" ---------------------------------------------------------------- -# .SH "OPTIONS" -# .sp -# In the following option flags, the version with "i" designates the input stream, "o" the output stream, and the version without prefix sets the option for both input and output stream\&. For example: \-\-irs sets the input record separator, \-\-ors the output record separator, and \-\-rs sets both the input and output separator to the given value\&. -# .SS "SEPARATOR" -# .PP -# \-\-rs, \-\-irs, \-\-ors -# .RS 4 -# Record separators, defaulting to newline -# .RE -# .PP -# \-\-fs, \-\-ifs, \-\-ofs, \-\-repifs -# .RS 4 -# Field separators, defaulting to "," -# .RE -# .PP -# \-\-ps, \-\-ips, \-\-ops -# .RS 4 -# Pair separators, defaulting to "=" -# .RE -# .SS "DATA\-FORMAT" -# .PP -# \-\-dkvp, \-\-idkvp, \-\-odkvp -# .RS 4 -# Delimited key\-value pairs, e\&.g "a=1,b=2" (default) -# .RE -# .PP -# \-\-nidx, \-\-inidx, \-\-onidx -# .RS 4 -# Implicitly\-integer\-indexed fields (Unix\-toolkit style) -# .RE -# .PP -# \-\-csv, \-\-icsv, \-\-ocsv -# .RS 4 -# Comma\-separated value (or tab\-separated with \-\-fs tab, etc\&.) -# .RE -# .PP -# \-\-pprint, \-\-ipprint, \-\-opprint, \-\-right -# .RS 4 -# Pretty\-printed tabular (produces no output until all input is in) -# .RE -# .PP -# \-\-pprint, \-\-ipprint, \-\-opprint, \-\-right -# .RS 4 -# Pretty\-printed tabular (produces no output until all input is in) -# .RE -# .sp -# \-p is a keystroke\-saver for \-\-nidx \-\-fs space \-\-repifs -# .SS "NUMERICAL FORMAT" -# .PP -# .RS 4 -# Sets the numerical format given a printf\-style format string\&. -# .RE -# .SS "OTHER" -# .PP -# .RS 4 -# Seeds the random number generator used for put/filter -# urand() -# with a number n of the form 12345678 or 0xcafefeed\&. -# .RE -# .SS "VERBS" -# .sp -# .it 1 an-trap -# .nr an-no-space-flag 1 -# .nr an-break-flag 1 -# .br -# .ps +1 -# \fBcut\fR -# .RS 4 -# .sp -# Usage: mlr cut [options] -# .sp -# Passes through input records with specified fields included/excluded\&. -# .PP -# \-f {a,b,c} -# .RS 4 -# Field names to include for cut\&. -# .RE -# .PP -# \-o -# .RS 4 -# Retain fields in the order specified here in the argument list\&. Default is to retain them in the order found in the input data\&. -# .RE -# .PP -# \-x|\-\-complement -# .RS 4 -# Exclude, rather that include, field names specified by \-f\&. -# .RE -# .RE -# .sp -# .it 1 an-trap -# .nr an-no-space-flag 1 -# .nr an-break-flag 1 -# .br -# .ps +1 -# \fBfilter\fR -# .RS 4 -# .sp -# prints the AST (abstract syntax tree) for the expression, which gives full transparency on the precedence and associativity rules of Miller\(cqs grammar\&. Please use a dollar sign for field names and double\-quotes for string literals\&. Miller built\-in variables are NF, NR, FNR, FILENUM, FILENAME, PI, E\&. -# .sp -# Examples: -# .sp -# .if n \{\ -# .RS 4 -# .\} -# .nf -# mlr filter \*(Aqlog10($count) > 4\&.0\*(Aq -# mlr filter \*(AqFNR == 2 (second record in each file)\*(Aq -# mlr filter \*(Aqurand() < 0\&.001\*(Aq (subsampling) -# mlr filter \*(Aq$color != "blue" && $value > 4\&.2\*(Aq -# mlr filter \*(Aq($x<\&.5 && $y<\&.5) || ($x>\&.5 && $y>\&.5)\*(Aq -# .fi -# .if n \{\ -# .RE -# .\} -# .sp -# Please see http://johnkerl\&.org/miller/doc/reference\&.html for more information including function list\&. -# .RE -# .sp -# .it 1 an-trap -# .nr an-no-space-flag 1 -# .nr an-break-flag 1 -# .br -# .ps +1 -# .\" ---------------------------------------------------------------- -# .RE -# .RE - -# .\" ---------------------------------------------------------------- -# .SH "AUTHOR" -# .sp -# miller is written by John Kerl \&. -# .sp -# This manual page has been composed from miller\(cqs help output by Eric MSP Veith \&. -# .SH "SEE ALSO" -# .sp -# sed(1), awk(1), cut(1), join(1), sort(1), RFC 4180: Common Format and MIME Type for Comma\-Separated Values (CSV) Files, the miller website http://johnkerl\&.org/miller/doc