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