-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathadventuresintechland.el
463 lines (406 loc) · 17.3 KB
/
adventuresintechland.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
;;; adventuresintechland.el --- my personal CMS -*- lexical-binding: t -*-
;;; package --- Summary
;;; Commentary:
;; TODO
;; use defvar and defconst to declare things
;; the way this should work is
;; 1) I type the contents in a buffer
;; 2) I call the dailyIndex function
;; 3) it inserts the buffer contents into the index
;; 4) it creates the RSS item from the first paragraph (I need to itendify it)
;; 5) it updates the daytracker
;; 6) boom
;;
;; that way, I can focus back on html/css, write about that, including the web engineer thing
;; and that's more fun.
;;; Code:
(setq debug-on-error t)
;;;;;;;;;;;;;;;;;;;;;;;;;
;;; constants
(defconst jc-repositoryPath "/Users/suzume/Documents/Repositories/brandelune.github.io/")
(defconst jc-dayTrackerPath (concat jc-repositoryPath "dayTracker.txt"))
(defconst jc-rssFile (concat jc-repositoryPath "adventuresintechland.xml"))
(defconst jc-indexPath (concat jc-repositoryPath "index.html"))
(defconst jc-tomorrowFile (concat jc-repositoryPath "tomorrow.html"))
(defconst jc-tomorrow "<a href=\"../../../tomorrow.html\" hreflang=\"en\" rel=\"next\">tomorrow</a>")
(defconst jc-ghPagesURL "https://github.com/brandelune/brandelune.github.io/commits/gh-pages")
(defconst jc-siteRoot "https://github.com/brandelune/brandelune.github.io/")
(defconst jc-faviconURL "https://brandelune.github.io/favicon/")
(defconst jc-rssReferences "<a href=\"https://brandelune.github.io/adventuresintechland.xml\"><img src=\"https://www.mozilla.org/media/img/trademarks/feed-icon-28x28.e077f1f611f0.png\" width=\"15px\" height=\"15px\" alt=\"rss feed\" /></a>")
(defconst jc-baseCSSLink "../../adventuresintechland.css")
(defconst jc-dailyCSSLink "./adventuresintechland.css")
(defconst jc-todayNavigationContents "<p class=\"navigation\">
<a href=\"%1$s\" hreflang=\"en\" rel=\"prev\">%2$s</a>
<a href=\"../../../index.html\" hreflang=\"en\">index</a>
<a href=\"%3$s\">gh-pages</a>
<a href=\"../../../adventuresintechland.html\" hreflang=\"en\">todo</a>
%4$s
</p>")
(defconst jc-todayHeaderContents "<html>
<head lang=\"en-us\">
<title>%1$s</title>
<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />
<meta name=\"msapplication-TileColor\" content=\"#FFFFFF\" />
<meta name=\"msapplication-TileImage\" content=\"%4$sfavicon-144.png\" />
<meta name=\"msapplication-config\" content=\"%4$sbrowserconfig.xml\" />
<link rel=\"shortcut icon\" href=\"%4$sfavicon.ico\" />
<link rel=\"icon\" sizes=\"16x16 32x32 64x64\" href=\"%4$sfavicon.ico\" />
<link rel=\"icon\" type=\"image/png\" sizes=\"196x196\" href=\"%4$sfavicon-192.png\" />
<link rel=\"icon\" type=\"image/png\" sizes=\"160x160\" href=\"%4$sfavicon-160.png\" />
<link rel=\"icon\" type=\"image/png\" sizes=\"96x96\" href=\"%4$sfavicon-96.png\" />
<link rel=\"icon\" type=\"image/png\" sizes=\"64x64\" href=\"%4$sfavicon-64.png\" />
<link rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"%4$sfavicon-32.png\" />
<link rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"%4$sfavicon-16.png\" />
<link rel=\"apple-touch-icon\" href=\"%4$sfavicon-57.png\" />
<link rel=\"apple-touch-icon\" sizes=\"114x114\" href=\"%4$sfavicon-114.png\" />
<link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"%4$sfavicon-72.png\" />
<link rel=\"apple-touch-icon\" sizes=\"144x144\" href=\"%4$sfavicon-144.png\" />
<link rel=\"apple-touch-icon\" sizes=\"60x60\" href=\"%4$sfavicon-60.png\" />
<link rel=\"apple-touch-icon\" sizes=\"120x120\" href=\"%4$sfavicon-120.png\" />
<link rel=\"apple-touch-icon\" sizes=\"76x76\" href=\"%4$sfavicon-76.png\" />
<link rel=\"apple-touch-icon\" sizes=\"152x152\" href=\"%4$sfavicon-152.png\" />
<link rel=\"apple-touch-icon\" sizes=\"180x180\" href=\"%4$sfavicon-180.png\" />
<link rel=\"stylesheet\" type=\"text/css\" href=\"%2$s\" class=\"baseCSS\"/>
<link rel=\"stylesheet\" type=\"text/css\" href=\"%3$s\" class=\"dailyCSS\"/>
<meta charset=\"UTF-8\" />
</head>")
(defconst jc-todayTemplateContents "%1$s
<body>
%2$s
<p id=\"episode\"><em>Adventures in Tech Land. Season %7$s. Episode %8$s</em></p>
<h1>%4$s %9$s</h1>
<p id=\"title item\">%3$s, %10$sth day</p>
<h2>%5$s</h2>
<p id=\"first sub-title item\">%6$s</p>
%2$s
</body>
</html>")
(defconst jc-myRSSTemplate "<item>
<title>%1$s</title>
<link>https://brandelune.github.io/%2$s/index.html</link>
<guid>https://brandelune.github.io/%2$s/index.html</guid>
<pubDate>%3$s</pubDate>
<description>%4$s</description>
</item>
")
;;; variables
(defvar jc-lastdayList)
(defvar jc-lastdayLink)
(defvar jc-lastdayDate)
(defvar jc-todayList)
(defvar jc-todayHeader)
(defvar jc-todayTemplate)
(defvar jc-todayNavigation)
(defvar jc-todayPath)
(defvar jc-todayIndex)
(defvar jc-todayDate)
(defvar jc-seasonNumber)
(defvar jc-seasonEpisode)
(defvar jc-totalDays)
(defvar jc-newDayTracker)
(defvar monthMaxDay)
;;;;;;;;;;;;;;;;;;;;;;;;;
(defun dailyIndex (today lastday title subtitle firstpar)
"Create an html file for TODAY with LASTDAY TITLE SUBTITLE FIRSTPAR.
The contents has to be filled manually, later."
;; Create values for the new index, based on yesterday's values in dayTracker.txt.
(save-current-buffer
(set-buffer (find-file-noselect jc-dayTrackerPath))
(goto-char (point-min))
(search-forward-regexp "\\([0-9]*\\.[0-9]*\\) \\([0-9]*\\) \\([0-9]*\\) \\([0-9]*\\)")
(setq jc-lastdayDate (cl-fourth (decode-time (string-to-number (match-string 1))))
seasonNumber (match-string 2)
totalDays (string-to-number (match-string 3))
newTotalDays (+ 1 totalDays)
currentEpisode (string-to-number (match-string 4))
newSeasonEpisode (+ 1 currentEpisode))
(kill-buffer))
;; Input data
(interactive (list
(read-number "Date: " (cl-fourth (decode-time (float-time))))
(read-number "Previous date: " jc-lastdayDate)
(read-string "Title: " )
(read-string "Sub-title: ")
(read-string "First paragraph: ")))
;; Create data for last day
(setq jc-lastdayList (myDate lastday)
jc-lastday (concat (my0Padding (cl-second jc-lastdayList)) (my0Padding (cl-third jc-lastdayList)))
jc-lastdayLink (concat (file-name-as-directory "../../../")
(file-name-as-directory (number-to-string (cl-first jc-lastdayList)))
(file-name-as-directory (my0Padding (cl-second jc-lastdayList)))
(file-name-as-directory (my0Padding (cl-third jc-lastdayList)))
"index.html")
jc-lastdayIndex (concat (file-name-as-directory jc-repositoryPath)
(file-name-as-directory (number-to-string (cl-first jc-lastdayList)))
(file-name-as-directory (my0Padding (cl-second jc-lastdayList)))
(file-name-as-directory (my0Padding (cl-third jc-lastdayList)))
"index.html"))
;; Create data for today
(setq jc-todayList (myDate today)
jc-todaySubPath (concat (file-name-as-directory (number-to-string (cl-first jc-todayList)))
(file-name-as-directory (my0Padding (cl-second jc-todayList)))
(my0Padding (cl-third jc-todayList)))
jc-todayPath (concat (file-name-as-directory jc-repositoryPath)
(file-name-as-directory jc-todaySubPath))
jc-todayRelativeIndex (concat (file-name-as-directory "../../../")
(file-name-as-directory jc-todaySubPath)
"index.html")
jc-todayIndex (concat (file-name-as-directory jc-todayPath) "index.html")
jc-todayDate (concat (number-to-string (cl-first jc-todayList)) "/" (my0Padding (cl-second jc-todayList)) "/" (my0Padding (cl-third jc-todayList)))
jc-todayLinkName (concat (my0Padding (cl-second jc-todayList)) (my0Padding (cl-third jc-todayList))))
;; Create navigation
(setq jc-todayNavigation
(format jc-todayNavigationContents
jc-lastdayLink ;; 1$
jc-lastday ;; 2$
jc-ghPagesURL ;; 3$
jc-tomorrow ;; 4$
))
;; Create <head> contents
(setq jc-todayHeader
(format jc-todayHeaderContents
title ;; 1$
jc-baseCSSLink ;; 2$
jc-dailyCSSLink ;; 3$
jc-faviconURL ;; 4$
))
;; Create today's template
(setq jc-todayTemplate
(format jc-todayTemplateContents
jc-todayHeader ;; 1$
jc-todayNavigation ;; 2$
jc-todayDate ;; 3$
title ;; 4$
subtitle ;; 5$
firstpar ;; 6$
seasonNumber ;; 7$
jc-seasonEpisode ;; 8$
jc-rssReferences ;; 9$
jc-totalDays ;; 10$
))
(make-directory jc-todayPath t)
(myInsert jc-todayTemplate "" jc-todayIndex)
(myInsert "" "" jc-dailyCSSLink)
(myDailyRSSItem title today firstpar)
;; Update the dayTracker data
(save-current-buffer
(set-buffer (find-file-noselect jc-dayTrackerPath))
(goto-char (point-min))
(insert (format "%s %s %s %s\n" (float-time) seasonNumber jc-totalDays jc-seasonEpisode))
(save-buffer)
(kill-buffer))
;; update the previous page
(setq jc-todayDayAnchor
(concat "<a href=\"" jc-todayRelativeIndex "\" hreflang=\"en\" rel=\"next\">" jc-todayLinkName "</a>"))
(myReplace
jc-tomorrow
jc-todayDayAnchor
jc-lastdayIndex)
;; update the root index
;; 1. replace the link to the "last day" update1
(let* ((oldLastDayHref (concat "<a href=\"./"
(file-name-as-directory (number-to-string (cl-first jc-lastdayList)))
(file-name-as-directory (my0Padding (cl-second jc-lastdayList)))
(file-name-as-directory (my0Padding (cl-third jc-lastdayList)))
"index.html\" hreflang=\"en\" rel=\"prev\" id=\"update1\">last day</a>"))
(newLastDayHref (concat "<a href=\"./"
(file-name-as-directory (number-to-string (cl-first jc-todayList)))
(file-name-as-directory (my0Padding (cl-second jc-todayList)))
(file-name-as-directory (my0Padding (cl-third jc-todayList)))
"index.html\" hreflang=\"en\" rel=\"prev\" id=\"update1\">last day</a>")))
(myReplace
oldLastDayHref
newLastDayHref
jc-indexPath))
;; 2. replace the number of documented days update2
(let* ((oldTotaDaysH2 (format "<h2 id=\"update2\">Logbook, %1$s documented days</h2>"
(number-to-string totalDays)))
(newTotalDaysH2 (format "<h2 id=\"update2\">Logbook, %1$s documented days</h2>"
(number-to-string newTotalDays))))
(myReplace
oldTotaDaysH2
newTotalDaysH2
jc-indexPath))
;; 3. replace the season and episode number update3
(let* ((oldSeasonDataH3 (format "<h3 id=\"update3\">Season %1$s, %2$s episodes</h3>"
seasonNumber
currentEpisode))
(newSeasonDataH3 (format "<h3 id=\"update3\">Season %1$s, %2$s episodes</h3>"
seasonNumber
newSeasonEpisode)))
(myReplace
oldSeasonDataH3
newSeasonDataH3
jc-indexPath))
;; 4. add a link to the episode index update 4
(let* ((update4Marker "<ul id=\"update4\">\n")
(mainIndexTodayLiHref (format "<ul id=\"update4\">
<li style=\"list-style-type:square;\"><a href=\"./%1$s/index.html\" hreflang=\"en\" id=\"%2$s\">%3$s</a> %4$s</li>
"
jc-todaySubPath
newTotalDays
(substring jc-todaySubPath 2)
title
)))
(myReplace
update4Marker
mainIndexTodayLiHref
jc-indexPath))
;; update the tomorrow file with the new "last day"
(let* ((oldLastDayHref (concat "<a href=\"./"
(file-name-as-directory (number-to-string (cl-first jc-lastdayList)))
(file-name-as-directory (my0Padding (cl-second jc-lastdayList)))
(file-name-as-directory (my0Padding (cl-third jc-lastdayList)))
"index.html\" hreflang=\"en\" rel=\"prev\" id=\"update1\">last day</a>"))
(newLastDayHref (concat "<a href=\"./"
(file-name-as-directory (number-to-string (cl-first jc-todayList)))
(file-name-as-directory (my0Padding (cl-second jc-todayList)))
(file-name-as-directory (my0Padding (cl-third jc-todayList)))
"index.html\" hreflang=\"en\" rel=\"prev\" id=\"update1\">last day</a>")))
(myReplace
oldLastDayHref
newLastDayHref
jc-tomorrowFile))
;; open index file for completion
(find-file jc-todayIndex)
)
;;;;;;;;;;;;;;;;;;;;;;;;;
(defun myDailyRSSItem (title date desc)
"Insert the daily RSS feed with TITLE DATE and DESC."
;;;; TODO add default value for link
(interactive (list
(read-string "Title: ")
(read-number "Date: " (cl-fourth (decode-time (float-time) t)))
(read-string "Description: ")))
(let* ((jc-myRSSTemplateContents (format jc-myRSSTemplate
title ;; 1$
(cl-fifth (myDate date)) ;; 2$
(cl-fourth (myDate date)) ;; 3$
desc ;; 4$
)))
(myInsert
jc-myRSSTemplateContents
"<!-- place new items above this line -->"
jc-rssFile)
))
;;;;;;;;;;;;;;;;;;;;;;;;;
(defun ManageDailyEntry ()
"Create the current page, update the main index, the RSS feed, the previous page."
)
;;;;;;;;;;;;;;;;;;;;;;;;;
(defun my0Padding (number)
"Add a 0 string to one digit NUMBER.
This is used here to represent dates as in 01/01/2021"
;; string-pad "string" "length of padding" "thing to pad with" "pad from start if t"
(string-pad (number-to-string number) 2 48 t))
;; old code
;; (if (< number 10)
;; (format "0%s" number)
;; (number-to-string number)))
;; (my0Padding 3) -> "03"
;; (my0Padding 10) -> "10"
;; TODO add option to "number-to-string" so that the padding can happen there
;; // Defined in ~/Documents/Code/emacs/src/data.c
;;;;;;;;;;;;;;;;;;;;;;;;;
(defun myDate (day)
"Create a plausible (year month DAY) list.
Since I only enter a date for the current entry, I must compute the
previous day and the next days according to what's plausible. It is
expected that I enter a possible date."
;;;; TODO add error tests
;;;; (myDate 29) in February 2024, leap year, returns something like
;;;; (2024 2 29 "Sun, 29 Feb 2024 15:02:03 UT" "2024/2/29")
(let* (
(Today (decode-time (float-time)))
(thisMonth (cl-fifth Today))
(nextMonth (if (= 12 thisMonth)
1
(+ thisMonth 1)))
(lastMonth (if (= 1 thisMonth)
12
(- thisMonth 1)))
(thisYear (cl-sixth Today))
(nextYear (+ thisYear 1))
(lastYear (- thisYear 1))
(monthMaxDay
(cond
((member thisMonth '(1 3 5 7 8 10 12)) 31)
((member thisMonth '(4 6 9 11)) 30)
((and (= 2 thisMonth)
(= 0 (mod (cl-sixth (decode-time (float-time))) 4))) 29)
(t 28)))
(myDay (if (> day monthMaxDay) monthMaxDay day))
(dateDifference (- (cl-fourth Today) (abs myDay)))
(myMonth (cond ((> 24 (abs dateDifference)) thisMonth)
((natnump dateDifference) nextMonth)
(t lastMonth)))
(myYear (cond ((= myMonth thisMonth) thisYear)
((and (= myMonth nextMonth) (= myMonth 1)) nextYear)
(t lastYear)))
(rssDate (concat (format-time-string "%a, " (current-time) t)
(number-to-string myDay)
(format-time-string " %b %Y %H:%m:%S UT" (current-time) t)))
(linkDate (format "%1$s/%2$s/%3$s" myYear (my0Padding myMonth) (my0Padding myDay))))
(list myYear myMonth myDay rssDate linkDate)))
;;;;;;;;;;;;;;;;;;;;;;;;;
(defun myInsert (myText myMarker myFile)
"Insert MYTEXT at MYMARKER in MYFILE.
This is used to insert the RSS part of the feed for that day
at the end of the file, before the closing headers."
(save-current-buffer
;; Record which buffer is current; execute BODY; make that buffer current.
(set-buffer (find-file-noselect myFile))
;; Make buffer BUFFER-OR-NAME current for editing operations.
;; Read file FILENAME into a buffer and return the buffer.
(goto-char (point-min))
;; Set point to POSITION, a number or marker.
;; Return the minimum permissible value of point in the current buffer.
(if (not (search-forward myMarker nil t))
;; Search forward from point for STRING.
(progn
(kill-buffer)
(user-error (format "%s was not found" myMarker)))
;; user-error seems to abort the rest of the progn, hence the need to put kill-buffer above
(progn
(goto-char (point-min))
(goto-char (- (search-forward myMarker) (length myMarker)))
(insert myText)
(indent-region (point-min) (point-max))
;; not sure I want to indent if I use <pre> blocks in the inserted strings
(save-buffer)
(kill-buffer)))))
;;;;;;;;;;;;;;;;;;;;;;;;;
(defun myReplace (fromString toString myFile)
"Replace fromString with toString in MYFILE."
(save-current-buffer
;; Record which buffer is current; execute BODY; make that buffer current.
(set-buffer (find-file-noselect myFile))
;; Make buffer BUFFER-OR-NAME current for editing operations.
;; Read file FILENAME into a buffer and return the buffer.
(goto-char (point-min))
;; Set point to POSITION, a number or marker.
;; Return the minimum permissible value of point in the current buffer.
(if (not (search-forward fromString nil t))
;; Search forward from point for STRING.
(progn
(kill-buffer)
(user-error (format "%s was not found" fromString)))
;; user-error seems to abort the rest of the progn, hence the need to put kill-buffer above
(progn
(goto-char (point-min))
(replace-string fromString toString)
(save-buffer)
(kill-buffer)))))
;;;;;;;;;;;;;;;;;;;;;;;;;
(defun narrowToEditZone ()
"Narrow the index page to the area to edit."
;;;; search id = episode
;;;; goto beginning of line
;;;; set mark
;;;; search id = first sub-title item
;;;; goto to end of line
;;;; narrow-to-region
)
;;;;;;;;;;;;;;;;;;;;;;;;;
(provide 'adventuresintechland)
;;; adventuresintechland.el ends here