Skip to content

Commit bccf241

Browse files
Tiuxitgallone
and
tgallone
authored
Scripts: Add python script to generate man page (#1392)
* ✨ Add man generating script * ✨ Add arguments and description * 🐛 Add shebang * 📝 Add documentation & text for sections * 🐛 Fix italic text (italic is not supported for man pages) * 🗑️ Remove .1 generated file * ✏️ Fix type "abbreviation" gen-man.py:24 * 🐛 Fix invalid escape sequence * ✨ Add version finder * ✨ Example & config sections * 🗑️ Delete generated .1 file --------- Co-authored-by: tgallone <[email protected]>
1 parent c70c37c commit bccf241

File tree

1 file changed

+273
-0
lines changed

1 file changed

+273
-0
lines changed

scripts/gen-man.py

+273
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,273 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Python script to generate a man page for the command `fastfetch`.
4+
The man content will be printed to stdout so you will need to
5+
pipe it to a file if you want to save it.
6+
The command options will be generated using a JSON file.
7+
For the format of the JSON file, see https://github.com/fastfetch-cli/fastfetch/blob/dev/src/data/help.json
8+
"""
9+
10+
from json import load
11+
from datetime import date
12+
from re import search
13+
14+
15+
###### Text Decorations Tags ######
16+
17+
startUnderline = "\\fI" # start underline text tag
18+
endUnderline = "\\fR" # end underline text tag
19+
20+
startBold = "\\fB" # start bold text tag
21+
endBold = "\\fR" # end bold text tag
22+
23+
24+
###### Parameters ######
25+
26+
# path to the JSON option file
27+
pathToHelpFile = "../src/data/help.json"
28+
# man page section
29+
manSection = 1
30+
# title (center header)
31+
titlePage = "Fastfetch man page"
32+
# date (center footer)
33+
todayDate = date.today().strftime("%b %d %Y") # format : "Month (abbreviation) Day Year"
34+
# file to fastfetch version (left footer)
35+
pathToVersionFile = "../CMakeLists.txt"
36+
37+
38+
###### Sections Text ######
39+
40+
# text displayed in the "NAME" section
41+
nameSection = "\
42+
fastfetch - a neofetch-like tool for fetching system \
43+
information and displaying them in a pretty way"
44+
45+
# text displayed in the "DESCRIPTION" section
46+
descriptionSection = "\
47+
A maintained, feature-rich and performance \
48+
oriented, neofetch like system information tool."
49+
50+
# text displayed at the beginning of the "OPTIONS" section
51+
optionSection = "\
52+
Parsing is not case sensitive. E.g. \\fB--lib-PCI\\fR \
53+
is equal to \\fB--Lib-Pci\\fR. \
54+
\n\n\
55+
If a value is between square brakets, it is optional. \
56+
An optional boolean value defaults to true if not \
57+
specified. \
58+
\n\n\
59+
More detailed help messages for each options can be \
60+
printed with \\fB-h <option_without_dash_prefix>\\fR. \
61+
\n\n\
62+
All options can be made permanent with command \
63+
\\fBfastfetch <options> --gen-config\\fR. \
64+
"
65+
66+
# text displayed in the "CONFIGURATION"
67+
configurationSection = f"\
68+
.SS Fetch Structure \n\
69+
The structure of a fetch describes the modules that should \
70+
be included in the output. It consists of a string of modules, \
71+
separated by a colon (:). To list all available modules, \
72+
use --list-modules \
73+
\n\n\
74+
.SS Config Files \n\
75+
Fastfetch uses JSONC based format for configuration. \
76+
Fastfetch doesn't generate config file automatically; \
77+
it should be generated manually by {startBold}--gen-config.{endBold} \
78+
The config file will be saved in \
79+
{startBold}~/.config/fastfetch/config.jsonc{endBold} by default. \
80+
\n\n\
81+
A JSONC config file is a JSON file that also supports comments \
82+
with (// and /* */). Those files must have the extension '.jsonc'. \
83+
\n\n\
84+
The specified configuration/preset files are searched in the following order: \
85+
\n\n\
86+
{startBold}1.{endBold} relative to the current working directory \
87+
\n\n\
88+
{startBold}2.{endBold} relative to ~/.local/share/fastfetch/presets/ \
89+
\n\n\
90+
{startBold}3.{endBold} relative to /usr/share/fastfetch/presets/ \
91+
\n\n\
92+
Fastfetch provides some default presets. List them with --list-presets. \
93+
"
94+
95+
# text displayed in the "EXAMPLE" section
96+
exampleSection = "\
97+
.SS Config files:\n\
98+
.nf \
99+
// ~/.config/fastfetch/config.jsonc \n\
100+
{\n\
101+
\"$schema\": \"https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json\",\n\
102+
\"modules\": [ \n\
103+
\"title\", \n\
104+
\"separator\", \n\
105+
\"module1\", \n\
106+
{ \n\
107+
\"type\": \"module2\", \n\
108+
\"module2-option\": \"value\" \n\
109+
} \n\
110+
]\n\
111+
} \n\
112+
.fi"
113+
114+
# text displayed in the "BUGS" section
115+
bugSection = "Please report bugs to : \
116+
https://github.com/fastfetch-cli/fastfetch/issues"
117+
118+
# text displayed in the "WIKI" section
119+
wikiSection = "Fastfetch github wiki : https://github.com/fastfetch-cli/fastfetch/wiki/Configuration"
120+
121+
122+
###### Argument decoration ######
123+
124+
### optional arguments tags ###
125+
126+
# if an optional argument is displayed as [?optArg] (with "optArg" underlined)
127+
# this value should be f"[?{startUnderline}"
128+
startOptionalArgument = f"[{startUnderline}?"
129+
# if an optional argument is displayed as [?optArg] (with "optArg underlined")
130+
# this value should be f"{endUnderline}]"
131+
endOptionalArgument = f"{endUnderline}]"
132+
133+
### mandatory arguments tags ###
134+
startMandatoryArgument = f"{startUnderline}"
135+
endMandatoryArgument = f"{endUnderline}"
136+
137+
def generateManPage():
138+
139+
# importing the JSON file
140+
try:
141+
with open(pathToHelpFile, 'r') as jsonFile:
142+
helpFileData = load(jsonFile) # json.load
143+
jsonFile.close()
144+
except IOError as error:
145+
print("Error with file", pathToHelpFile, ":", error)
146+
return
147+
148+
149+
######## Start printing the generated .1 file ########
150+
151+
152+
###### header, footer & config #####
153+
154+
print(f".TH man {manSection}", end=" ")
155+
print(f"\"{todayDate}\"", end=" ")
156+
157+
# version number
158+
try:
159+
with open(pathToVersionFile, 'r') as versionFile:
160+
161+
# research version number in file with regex
162+
for line in versionFile:
163+
researchVersion = search("^\s*VERSION (\d+\.\d+\.\d+)$", line) # re.search()
164+
if (researchVersion != None):
165+
versionNumber = "".join(line[researchVersion.start():researchVersion.end()].split(" "))
166+
versionNumber = versionNumber[:7] + " " + versionNumber[7:]
167+
break
168+
169+
versionFile.close()
170+
except IOError as error:
171+
print("Error with file", pathToHelpFile, ":", error)
172+
return
173+
174+
print(f"\"{versionNumber}\"", end=" ")
175+
print(f"\"{titlePage}\"")
176+
177+
178+
###### Name ######
179+
180+
print(".SH NAME")
181+
print(nameSection)
182+
183+
184+
##### Synopsis ######
185+
186+
print(".SH SYNOPSIS")
187+
print(".B fastfetch")
188+
print(f"[{startUnderline}OPTIONS{endUnderline}]")
189+
190+
191+
##### Description #####
192+
193+
print(".SH DESCRIPTION")
194+
print(descriptionSection)
195+
196+
197+
###### Wiki ######
198+
199+
print(".SH WIKI")
200+
print(wikiSection)
201+
202+
203+
###### Configuration ######
204+
205+
print(".SH CONFIGURATION")
206+
print(configurationSection)
207+
208+
209+
###### Options ######
210+
211+
print(".SH OPTIONS")
212+
print(optionSection)
213+
print()
214+
215+
# loop through every options sections
216+
for key, value in helpFileData.items():
217+
218+
# print new subsection
219+
print(f".SS {key}:")
220+
221+
# loop through every option in a section
222+
for option in value:
223+
# list of existing keys for this option
224+
keyList = option.keys()
225+
226+
# start a new "option" entry
227+
print(".TP")
228+
print(startBold, end="")
229+
230+
# short option (-opt)
231+
if "short" in keyList:
232+
print(f"\\-{ option['short'] }", end="")
233+
# if also have a long option, print a comma
234+
if "long" in keyList:
235+
print(", ", end="")
236+
237+
# long option (--option)
238+
if "long" in keyList:
239+
print(f"\\-\\-{ option['long'] }", end="")
240+
241+
print(endBold, end=" ")
242+
243+
# arguments
244+
if "arg" in keyList:
245+
# if argument is optional, print "[arg]"
246+
if "optional" in option["arg"].keys() and option["arg"]["optional"]:
247+
print(startOptionalArgument + option['arg']['type'] + endOptionalArgument, end="")
248+
249+
# if argument is mandatory, print "arg"
250+
else:
251+
print(startMandatoryArgument + option['arg']['type'] + endMandatoryArgument, end="")
252+
253+
# description
254+
print(f"\n {option['desc']} \n")
255+
256+
257+
###### Examples ######
258+
259+
print(".SH EXAMPLES")
260+
print(exampleSection)
261+
262+
263+
###### Bugs ######
264+
265+
print(".SH BUGS")
266+
print(bugSection)
267+
268+
269+
270+
271+
272+
if __name__ == "__main__":
273+
generateManPage()

0 commit comments

Comments
 (0)