mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-22 18:06:52 +00:00
* Support PPRINT barred input * regression-test files * output from `make dev` * doc updates
220 lines
6.8 KiB
Ruby
Executable file
220 lines
6.8 KiB
Ruby
Executable file
#!/usr/bin/env ruby
|
|
|
|
# ================================================================
|
|
# This is a manpage autogenerator for Miller. There are various tools out there
|
|
# for creating xroff-formatted manpages, but I wanted something with minimal
|
|
# external dependencies which would also automatically generate most of its
|
|
# output from the mlr executable itself. It turns out it's easy enough to get
|
|
# this in just a few lines of Ruby.
|
|
#
|
|
# Note for dev-viewing of the output:
|
|
# ./mkman.rb | groff -man -Tascii | less
|
|
# ================================================================
|
|
|
|
# ----------------------------------------------------------------
|
|
def main
|
|
# In case the user running this has a .mlrrc
|
|
ENV['MLRRC'] = '__none__'
|
|
|
|
# Live code-generation needs to be using mlr from *this* tree, not from
|
|
# somewhere else in the PATH.
|
|
unless File.executable?('../mlr')
|
|
$stderr.puts "#{$0}: Need ../mlr to exist: please check 'make build' in ../.."
|
|
exit 1
|
|
end
|
|
`../mlr --version`
|
|
unless $?.success?
|
|
$stderr.puts "#{$0}: Need '../../mlr --version' to succeed; please check 'make build' in ../.."
|
|
exit 1
|
|
end
|
|
ENV['PATH'] = '..:' + ENV['PATH']
|
|
|
|
print make_top
|
|
|
|
print make_section('NAME', [
|
|
"Miller \\\-\\\- like awk, sed, cut, join, and sort for name-indexed data such as CSV and tabular JSON."
|
|
])
|
|
|
|
print make_section('SYNOPSIS', [
|
|
`mlr --help`
|
|
])
|
|
|
|
print make_section('DESCRIPTION', [
|
|
"""Miller operates on key-value-pair data while the familiar Unix tools operate
|
|
on integer-indexed fields: if the natural data structure for the latter is the
|
|
array, then Miller's natural data structure is the insertion-ordered hash map.
|
|
This encompasses a variety of data formats, including but not limited to the
|
|
familiar CSV, TSV, and JSON. (Miller can handle positionally-indexed data as
|
|
a special case.) This manpage documents #{`mlr --version`.chomp}."""
|
|
])
|
|
|
|
print make_section('EXAMPLES', [
|
|
""
|
|
])
|
|
print make_code_block(`mlr help basic-examples`)
|
|
|
|
print make_section('FILE FORMATS', [])
|
|
print make_code_block(`mlr help file-formats`)
|
|
|
|
print make_section('HELP OPTIONS', [])
|
|
print make_code_block(`mlr help topics`)
|
|
|
|
print make_section('VERB LIST', [])
|
|
print make_code_block(`mlr help list-verbs-as-paragraph`)
|
|
|
|
print make_section('FUNCTION LIST', [])
|
|
print make_code_block(`mlr help list-functions-as-paragraph`)
|
|
|
|
section_names = `mlr help list-flag-sections`.split("\n")
|
|
for section_name in section_names
|
|
print make_section(section_name.upcase, [""])
|
|
print make_code_block(`mlr help show-help-for-section '#{section_name}'`)
|
|
end
|
|
|
|
print make_section('AUXILIARY COMMANDS', [])
|
|
print make_code_block(`mlr aux-list`)
|
|
|
|
print make_section('MLRRC', [])
|
|
print make_code_block(`mlr help mlrrc`)
|
|
|
|
print make_section('REPL', [])
|
|
print make_code_block(`mlr repl -h`)
|
|
|
|
verbs = `mlr help list-verbs`
|
|
print make_section('VERBS', [
|
|
""
|
|
])
|
|
verbs = verbs.strip.split("\n")
|
|
for verb in verbs
|
|
print make_subsection(verb, [])
|
|
print make_code_block(`mlr #{verb} -h`)
|
|
end
|
|
|
|
functions = `mlr help list-functions`
|
|
print make_section('FUNCTIONS FOR FILTER/PUT', [
|
|
""
|
|
])
|
|
functions = functions.strip.split("\n").uniq
|
|
for function in functions
|
|
print make_subsection(function, [])
|
|
text = `mlr help function '#{function}'`
|
|
text = text.sub(function + ' ', '')
|
|
print make_code_block(text)
|
|
end
|
|
|
|
keywords = `mlr help list-keywords`
|
|
print make_section('KEYWORDS FOR PUT AND FILTER', [
|
|
""
|
|
])
|
|
keywords = keywords.strip.split("\n").uniq
|
|
for keyword in keywords
|
|
print make_subsection(keyword, [])
|
|
text = `mlr help keyword '#{keyword}'`
|
|
print make_code_block(text)
|
|
end
|
|
|
|
print make_section('AUTHOR', [
|
|
"Miller is written by John Kerl <kerl.john.r@gmail.com>.",
|
|
"This manual page has been composed from Miller's help output by Eric MSP Veith <eveith@veith-m.de>."
|
|
])
|
|
print make_section('SEE ALSO', [
|
|
"awk(1), sed(1), cut(1), join(1), sort(1), RFC 4180: Common Format and MIME Type for " +
|
|
"Comma-Separated Values (CSV) Files, the Miller docsite https://miller.readthedocs.io"
|
|
])
|
|
end
|
|
|
|
# ================================================================
|
|
def make_top()
|
|
t = Time::new
|
|
stamp = t.gmtime.strftime("%Y-%m-%d")
|
|
|
|
# Portability definitions thanks to some asciidoc output
|
|
|
|
"""'\\\" t
|
|
.\\\" Title: mlr
|
|
.\\\" Author: [see the \"AUTHOR\" section]
|
|
.\\\" Generator: #{$0}
|
|
.\\\" Date: #{stamp}
|
|
.\\\" Manual: \\ \\&
|
|
.\\\" Source: \\ \\&
|
|
.\\\" Language: English
|
|
.\\\"
|
|
.TH \"MILLER\" \"1\" \"#{stamp}\" \"\\ \\&\" \"\\ \\&\"
|
|
.\\\" -----------------------------------------------------------------
|
|
.\\\" * Portability definitions
|
|
.\\\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
.\\\" 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
|
|
.\\\" -----------------------------------------------------------------
|
|
"""
|
|
end
|
|
|
|
# ----------------------------------------------------------------
|
|
def make_section(title, paragraphs)
|
|
retval = ".SH \"#{title}\"\n"
|
|
paragraphs.each do |paragraph|
|
|
retval += ".sp\n"
|
|
retval += groff_encode(paragraph) + "\n"
|
|
end
|
|
retval
|
|
end
|
|
|
|
# ----------------------------------------------------------------
|
|
def make_subsection(title, paragraphs)
|
|
retval = ".SS \"#{title}\"\n"
|
|
paragraphs.each do |paragraph|
|
|
retval += ".sp\n"
|
|
retval += groff_encode(paragraph) + "\n"
|
|
end
|
|
retval
|
|
end
|
|
|
|
# ----------------------------------------------------------------
|
|
def make_subsubsection(title, paragraphs)
|
|
retval = ".sp\n";
|
|
retval += "\\fB#{title}\\fR\n"
|
|
paragraphs.each do |paragraph|
|
|
retval += ".sp\n"
|
|
retval += groff_encode(paragraph) + "\n"
|
|
end
|
|
retval
|
|
end
|
|
|
|
# ----------------------------------------------------------------
|
|
def make_code_block(block)
|
|
retval = ".if n \\{\\\n"
|
|
retval += ".RS 0\n"
|
|
retval += ".\\}\n"
|
|
retval += ".nf\n"
|
|
# In case the line starts with a dot:
|
|
retval += block.gsub('\\', '\e').gsub(/^\./){'\&.'}
|
|
# In case the line starts with a single quote:
|
|
retval = retval.gsub(/^'/, '\(cq')
|
|
retval += ".fi\n"
|
|
retval += ".if n \\{\\\n"
|
|
retval += ".RE\n"
|
|
end
|
|
|
|
# ----------------------------------------------------------------
|
|
def groff_encode(line)
|
|
#line = line.gsub(/'/, '\(cq')
|
|
#line = line.gsub(/"/, '\(dq')
|
|
#line = line.gsub(/\./, '\&')
|
|
#line = line.gsub(/-/, '\-')
|
|
line = line.gsub(/\\([^-])/, '\e\1')
|
|
line = line.gsub(/^\./){'\&.'}
|
|
line
|
|
end
|
|
|
|
# ================================================================
|
|
main
|