mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-30 13:40:37 +00:00
Generate a UNIX man page (fixes #874)
This commit is contained in:
parent
1f45686843
commit
c0c7cef16c
@ -4,7 +4,8 @@ cmake_minimum_required(VERSION 3.16)
|
||||
# make_dist expects the version line to be on a line by itself after
|
||||
# the project line. When updating the version, check make_dist for all
|
||||
# the places it has to be updated. The doc configuration and CI build
|
||||
# also find the version number here.
|
||||
# also find the version number here. generate_auto_job also reads the
|
||||
# version from here.
|
||||
project(qpdf
|
||||
VERSION 11.7.0
|
||||
LANGUAGES C CXX)
|
||||
@ -312,9 +313,12 @@ endif()
|
||||
set(auto_job_inputs
|
||||
# Keep in sync with SOURCES in generate_auto_job
|
||||
generate_auto_job
|
||||
CMakeLists.txt
|
||||
manual/_ext/qpdf.py
|
||||
job.yml
|
||||
manual/cli.rst)
|
||||
manual/cli.rst
|
||||
manual/qpdf.1.in
|
||||
)
|
||||
|
||||
set(auto_job_outputs
|
||||
# Keep in sync with DESTS in generate_auto_job
|
||||
@ -323,7 +327,9 @@ set(auto_job_outputs
|
||||
libqpdf/qpdf/auto_job_help.hh
|
||||
libqpdf/qpdf/auto_job_schema.hh
|
||||
libqpdf/qpdf/auto_job_json_decl.hh
|
||||
libqpdf/qpdf/auto_job_json_init.hh)
|
||||
libqpdf/qpdf/auto_job_json_init.hh
|
||||
manual/qpdf.1
|
||||
)
|
||||
|
||||
if(GENERATE_AUTO_JOB)
|
||||
add_custom_command(
|
||||
|
@ -1,5 +1,8 @@
|
||||
2023-12-22 Jay Berkenbilt <ejb@ql.org>
|
||||
|
||||
* Generate a more complete qpdf "man page" from the same source as
|
||||
qpdf --help. Fixes #874.
|
||||
|
||||
* Allow the syntax "--encrypt --user-password=user-password
|
||||
--owner-password=owner-password --bits={40,128,256}" when
|
||||
encrypting PDF files. This is an alternative to the syntax
|
||||
|
@ -134,6 +134,12 @@ BANNER = f'''//
|
||||
// clang-format off
|
||||
//'''
|
||||
|
||||
MAN_BANNER = f'''.\\"
|
||||
.\\" This file is automatically generated by {whoami}.
|
||||
.\\" Edits will be automatically overwritten if the build is
|
||||
.\\" run in maintainer mode.
|
||||
.\\"
|
||||
'''
|
||||
|
||||
def warn(*args, **kwargs):
|
||||
print(*args, file=sys.stderr, **kwargs)
|
||||
@ -156,9 +162,11 @@ class Main:
|
||||
SOURCES = [
|
||||
# Keep this list in sync with CMakeLists.txt: auto_job_inputs
|
||||
whoami,
|
||||
'CMakeLists.txt',
|
||||
'manual/_ext/qpdf.py',
|
||||
'job.yml',
|
||||
'manual/cli.rst',
|
||||
'manual/qpdf.1.in',
|
||||
]
|
||||
# DESTS is a map to the output files this code generates. These
|
||||
# generated files, as well as those added to DESTS later in the
|
||||
@ -172,6 +180,7 @@ class Main:
|
||||
'schema': 'libqpdf/qpdf/auto_job_schema.hh',
|
||||
'json_decl': 'libqpdf/qpdf/auto_job_json_decl.hh',
|
||||
'json_init': 'libqpdf/qpdf/auto_job_json_init.hh',
|
||||
'man': 'manual/qpdf.1',
|
||||
# Others are added in top
|
||||
}
|
||||
# SUMS contains a checksum for each source and destination and is
|
||||
@ -277,7 +286,7 @@ class Main:
|
||||
for k, v in hashes.items():
|
||||
print(f'{k} {v}', file=f)
|
||||
|
||||
def generate_doc(self, df, f):
|
||||
def generate_doc(self, df, f, f_man):
|
||||
st_top = 0
|
||||
st_topic = 1
|
||||
st_option = 2
|
||||
@ -324,6 +333,23 @@ class Main:
|
||||
return True
|
||||
return False
|
||||
|
||||
def manify(text):
|
||||
lines = text.split('\n')
|
||||
out = []
|
||||
last_was_item = False
|
||||
for line in lines:
|
||||
if line.startswith('- '):
|
||||
last_was_item = True
|
||||
out.append('.IP \\[bu]')
|
||||
out.append(line[2:])
|
||||
elif last_was_item and line.startswith(' '):
|
||||
out.append(line[2:])
|
||||
else:
|
||||
last_was_item = False
|
||||
out.append(line)
|
||||
return '\n'.join(out)
|
||||
|
||||
last_option_topic = ''
|
||||
lineno = 0
|
||||
for line in df.readlines():
|
||||
if help_lines == 0:
|
||||
@ -366,6 +392,8 @@ class Main:
|
||||
self.all_topics.add(topic)
|
||||
print(f'ap.addHelpTopic("{topic}", "{short_text}",'
|
||||
f' R"({long_text})");', file=f)
|
||||
print(f'.SH {topic.upper()} ({short_text})', file=f_man)
|
||||
print(manify(long_text), file=f_man, end='')
|
||||
help_lines += 1
|
||||
state = st_top
|
||||
elif state == st_option:
|
||||
@ -389,6 +417,11 @@ class Main:
|
||||
self.jdata[option[2:]]['help'] = short_text
|
||||
print(f'ap.addOptionHelp("{option}", "{topic}",'
|
||||
f' "{short_text}", R"({long_text})");', file=f)
|
||||
if last_option_topic != topic:
|
||||
print('.PP\nRelated Options:', file=f_man)
|
||||
last_option_topic = topic
|
||||
print(f'.TP\n.B {option} \\-\\- {short_text}', file=f_man)
|
||||
print(manify(long_text), file=f_man, end='')
|
||||
help_lines += 1
|
||||
state = st_top
|
||||
if help_lines == 20:
|
||||
@ -400,6 +433,11 @@ class Main:
|
||||
print('ap.addHelpFooter("For detailed help, visit'
|
||||
' the qpdf manual: https://qpdf.readthedocs.io\\n");', file=f)
|
||||
print('}\n', file=f)
|
||||
print('''.SH SEE ALSO
|
||||
.PP
|
||||
For a summary of qpdf's options, please run \\fBqpdf \\-\\-help\\fR.
|
||||
A complete manual can be found at https://qpdf.readthedocs.io.
|
||||
''', file=f_man, end='')
|
||||
for i in self.referenced_topics:
|
||||
if i not in self.all_topics:
|
||||
raise Exception(f'help text referenced --help={i}')
|
||||
@ -412,6 +450,14 @@ class Main:
|
||||
warn(f'{whoami}: regenerating auto job files')
|
||||
self.validate(data)
|
||||
|
||||
version = None
|
||||
with open('CMakeLists.txt', 'r') as f:
|
||||
for line in f.readlines():
|
||||
if line.strip().startswith('VERSION '):
|
||||
version = line.strip().split(' ')[1]
|
||||
if version is None:
|
||||
raise Exception("can't read version from CMakeLists.txt")
|
||||
|
||||
# Keep track of which options are help options since they are
|
||||
# handled specially. Add the built-in help options to tables
|
||||
# that we populate as we read job.yml since we won't encounter
|
||||
@ -436,9 +482,15 @@ class Main:
|
||||
for i in self.init:
|
||||
print(i, file=f)
|
||||
with write_file(self.DESTS['help']) as f:
|
||||
with open('manual/cli.rst', 'r') as df:
|
||||
print(BANNER, file=f)
|
||||
self.generate_doc(df, f)
|
||||
with write_file(self.DESTS['man']) as f_man:
|
||||
print(MAN_BANNER, file=f_man, end='')
|
||||
with open('manual/qpdf.1.in', 'r') as m_in:
|
||||
for line in m_in.readlines():
|
||||
line = line.replace('@PROJECT_VERSION@', version)
|
||||
print(line, file=f_man, end='')
|
||||
with open('manual/cli.rst', 'r') as df:
|
||||
print(BANNER, file=f)
|
||||
self.generate_doc(df, f, f_man)
|
||||
|
||||
# Compute the json files after the config and arg parsing
|
||||
# files. We need to have full information about all the
|
||||
|
9
job.sums
9
job.sums
@ -1,5 +1,6 @@
|
||||
# Generated by generate_auto_job
|
||||
generate_auto_job bf44181b610d335511a41b6c2b9c3497d0b023a1ca2c8e4537b34cb6262ce173
|
||||
CMakeLists.txt 66e8f9bf15a0c3394b1b13baaf5a709f7af35a6f733cd173092168e87202c7a5
|
||||
generate_auto_job f64733b79dcee5a0e3e8ccc6976448e8ddf0e8b6529987a66a7d3ab2ebc10a86
|
||||
include/qpdf/auto_job_c_att.hh 4c2b171ea00531db54720bf49a43f8b34481586ae7fb6cbf225099ee42bc5bb4
|
||||
include/qpdf/auto_job_c_copy_att.hh 50609012bff14fd82f0649185940d617d05d530cdc522185c7f3920a561ccb42
|
||||
include/qpdf/auto_job_c_enc.hh 28446f3c32153a52afa239ea40503e6cc8ac2c026813526a349e0cd4ae17ddd5
|
||||
@ -8,10 +9,12 @@ include/qpdf/auto_job_c_pages.hh b3cc0f21029f6d89efa043dcdbfa183cb59325b6506001c
|
||||
include/qpdf/auto_job_c_uo.hh ae21b69a1efa9333050f4833d465f6daff87e5b38e5106e49bbef5d4132e4ed1
|
||||
job.yml 4f89fc7b622df897d30d403d8035aa36fc7de8d8c43042c736e0300d904cb05c
|
||||
libqpdf/qpdf/auto_job_decl.hh 9c6f701c29f3f764d620186bed92685a2edf2e4d11e4f4532862c05470cfc4d2
|
||||
libqpdf/qpdf/auto_job_help.hh ea1fdca2aa405bdf193732c5a2789c602efe2add3aa6e2dceecfacee175ce65c
|
||||
libqpdf/qpdf/auto_job_help.hh bbd37ac0e8b3e38892a328ca08829d6e71c31ea3ab6c1a91b5f6983018695ef9
|
||||
libqpdf/qpdf/auto_job_init.hh b4c2b3724fba61f1206fd3bae81951636852592f67a63ef9539839c2c5995065
|
||||
libqpdf/qpdf/auto_job_json_decl.hh 06caa46eaf71db8a50c046f91866baa8087745a9474319fb7c86d92634cc8297
|
||||
libqpdf/qpdf/auto_job_json_init.hh f5acb9aa103131cb68dec0e12c4d237a6459bdb49b24773c24f0c2724a462b8f
|
||||
libqpdf/qpdf/auto_job_schema.hh b53c006fec2e75b1b73588d242d49a32f7d3db820b1541de106c5d4c27fbb4d9
|
||||
manual/_ext/qpdf.py 6add6321666031d55ed4aedf7c00e5662bba856dfcd66ccb526563bffefbb580
|
||||
manual/cli.rst 28cc6b36b26377404022bab467e6a16085023fdfa5d9d419595ffcae6c69d531
|
||||
manual/cli.rst 7bbeb2f234ca3d095c069f52e4a3c5e42a525b5ef6231955d036a6313eaffcd2
|
||||
manual/qpdf.1 745cb32c1772e6d84ef962aca7a439ee045226ae547330778a4a3ba3cd8d25df
|
||||
manual/qpdf.1.in 436ecc85d45c4c9e2dbd1725fb7f0177fb627179469f114561adf3cb6cbb677b
|
||||
|
@ -37,10 +37,10 @@ description of the JSON input file format.
|
||||
)");
|
||||
ap.addHelpTopic("exit-status", "meanings of qpdf's exit codes", R"(Meaning of exit codes:
|
||||
|
||||
0: no errors or warnings
|
||||
1: not used by qpdf but may be used by the shell if unable to invoke qpdf
|
||||
2: errors detected
|
||||
3: warnings detected, unless --warning-exit-0 is given
|
||||
- 0: no errors or warnings
|
||||
- 1: not used by qpdf but may be used by the shell if unable to invoke qpdf
|
||||
- 2: errors detected
|
||||
- 3: warnings detected, unless --warning-exit-0 is given
|
||||
)");
|
||||
ap.addOptionHelp("--warning-exit-0", "exit-status", "exit 0 even with warnings", R"(Use exit status 0 instead of 3 when warnings are present. When
|
||||
combined with --no-warn, warnings are completely ignored.
|
||||
|
@ -22,7 +22,7 @@ if(BUILD_DOC)
|
||||
endif()
|
||||
|
||||
set(MANUAL_SRC ${qpdf_SOURCE_DIR}/manual)
|
||||
foreach(F qpdf.1 fix-qdf.1 zlib-flate.1)
|
||||
foreach(F fix-qdf.1 zlib-flate.1)
|
||||
configure_file(
|
||||
${MANUAL_SRC}/${F}.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/${F}
|
||||
@ -129,7 +129,7 @@ if(NOT WIN32)
|
||||
# environment, especially when all they do is refer people to the
|
||||
# manual.
|
||||
install(FILES
|
||||
${CMAKE_CURRENT_BINARY_DIR}/qpdf.1
|
||||
${qpdf_SOURCE_DIR}/manual/qpdf.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/fix-qdf.1
|
||||
${CMAKE_CURRENT_BINARY_DIR}/zlib-flate.1
|
||||
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1
|
||||
|
@ -184,10 +184,10 @@ Exit Status
|
||||
|
||||
Meaning of exit codes:
|
||||
|
||||
0: no errors or warnings
|
||||
1: not used by qpdf but may be used by the shell if unable to invoke qpdf
|
||||
2: errors detected
|
||||
3: warnings detected, unless --warning-exit-0 is given
|
||||
- 0: no errors or warnings
|
||||
- 1: not used by qpdf but may be used by the shell if unable to invoke qpdf
|
||||
- 2: errors detected
|
||||
- 3: warnings detected, unless --warning-exit-0 is given
|
||||
|
||||
The exit status of :command:`qpdf` may be interpreted as follows:
|
||||
|
||||
|
1109
manual/qpdf.1
Normal file
1109
manual/qpdf.1
Normal file
File diff suppressed because it is too large
Load Diff
@ -80,6 +80,11 @@ Planned changes for future 12.x (subject to change):
|
||||
``README-maintainer.md`` for a detailed explanation of how to
|
||||
maintain this.
|
||||
|
||||
- Package Enhancements:
|
||||
|
||||
- A UNIX man page is now automatically generated from the
|
||||
documentation. It contains the same text as ``qpdf --help=all``.
|
||||
|
||||
- Library Enhancements:
|
||||
|
||||
- Add C++ functions ``qpdf_c_wrap`` and ``qpdf_c_get_qpdf`` to the
|
||||
|
Loading…
Reference in New Issue
Block a user