Identifying a lethal mistake - after it happened: Notetaking Edition

Table of Contents

For a while now I use my own implementation of a notetaking system to quickly and efficiently create lecture notes, ready to be published, exported and reviewed. All within Emacs.

This solution worked perfectly and I took huge pride in it. It allowed me to focus on the lecture, utilizing only muscle memory to jot what was being taught down and, since my touch-typing skills are on point, ensuring that I would have quality material I could later study from.

It really worked. Until it failed.

And today it failed again.

The story

While writing the draft for this article I realized that this might have never happened if I had published my configuration earlier. Anyone seeing the code (even though I’m not proud of its quality), might have seen this mistake… Moral of the story: I should write about my notetaking setup, detailing the faulty parts and asking for criticism maybe…

Sometime this Fall Semester (on a Monday), I was at my university, attending a lecture on Stochastic Signals (you can see more about the course here) when suddenly my working file was corrupted and I lost everything I had written till that point. Even my automatically generated backup files (which I had kept active in my configuration for moments like these) could not help me. Something mysterious had happened.

I could not understand what, but since the lecture was still going, I focused on writing down what was left of it. Later, when it was over, I added as much as I could remember, completing it (even though its quality could not be compared to the original one).

Since I believed it was my error, I did not waste any time into trying to see what went on. After all, the file was not corrupted in a way I could understand: an empty file was just written on top of it, giving me the blank template I have before adding content to a lecture.

Today, as I was watching Strang’s wonderful lecture on eigenvalues and eigenvectors, I stopped to go back to a previous one: I had forgotten how to calculate the null space. I decided to create a reference for that lecture as well, to avoid spending more time in the future to revisit the lecture: I can visit my notes in a much more timely fashion. However, instead of visiting a new file I … lost my lecture notes at the blink of an eye.

And that is when I saw how naive I was when I wrote this little part of the code.

The Doombringer

This is the function that I had originally created (and used till this day)

(defun chatziiola/set-lectures-filename(course)
  "Returns the lecture's title in a format: lec_<course>_<date>.org"
  (concat "lec_" course  "_" (format-time-string "%Y%m%d"(current-time)) ".org"))

The description was:

Set the lecture’s filename. I have experimented for a long time with this function but i think that the ’lec_<course>_<date>.org’ is an ideal format.

If you did not see what became so painfully apparent to me today: I do not check whether this file exists (nor does the function the calls this one). I just assume… a lot of things.

Understanding my mistake

Back when I created this function I hoped my files would get named like that : lec_course_lecnumber_title.org.

The thought that the title was unknown at the beginning of the lecture (at least for the non-recorded ones) had not come to my mind and the lecnumber implementation was equally problematic: I did not want to spend any more time in designing the script, I wanted it to be functional and use it. However, my implementations of lecnumber were at that point unacceptable, forcing me to settle on a much simpler format: lec_course_simpledate.org

The only drawback with this format would be apparent only when I manually visited the lectures directory, which was more than acceptable since I would solely visit these files through my set of custom functions. Furthermore, since my lecture files are plain-text even a simple bash snippet such as this one could do the job:

for i in lec_SSD*; do echo $i; head -10 $i | grep 'TITLE'; done 

Additionally, I just that only one lecture per course would be created per day, so it is completely unnecessary to implement checks, or add more information in the file title to separate lecture files it from each other. After all, I wanted to keep it minimal.

Free tip: When you reach a point, even in scripts as simple as my notetaking ones, where you can spend 5 minutes implementing a check, please do it, no matter how silly it feels at the moment. I had it as a rule for myself, but thought that, in this occasion, I could do without it. Look at me now: Writing this article, after losing my notes.

It all becomes clear now: I either need to make it impossible for a lecture to have the same filename as another lecture or to make sure that I check whether the file exists.

Implementing solutions

Impossible filename approach

Extremely safe yet against my simple-filenames policy (keeping filenames as simple and organized as possible to reduce visual clutter when manually visiting these dirs)

(defun chatziiola/set-lectures-filename(course)
  "Returns the lecture's title in a format: lec_<course>_<date>.org. "
    ; This function was modified on <2023-01-10 Tue>, to fix a bug: I could not
    ; start a second lecture for the same course on the same day without
    ; overwriting the initial lecture
    (concat "lec_" course  "_" (format-time-string "%Y%m%d_%H%M%S"(current-time)) ".org"))

Check for file approach

(defun chatziiola/set-lectures-filename(course)
  "Returns the lecture's title in a format: lec_<course>_<date>.org. "
    ; This function was modified on <2023-01-10 Tue>, to fix a bug: I could not
    ; start a second lecture for the same course on the same day without
    ; overwriting the initial lecture
    (let* ((filename (concat "lec_" course  "_" (format-time-string "%Y%m%d"(current-time)) ".org"))
	    (lecpath (expand-file-name filename (expand-file-name (concat "course_" course) chatziiola/lectures-dir))))
	;; If the file already exists
	(if (file-exists-p lecpath)
	    (setq-local filename (concat "lec_" course  "_" (format-time-string "%Y%m%d_%H%M%S"(current-time)) "_"
	    ;; I use or so that I can always press enter there :P
		    (read-string "A lecture already existed with this filename. Enter complementary information (empty appends hourminutesecond): ")
		    (format-time-string "%H%M%S"(current-time)))

Selecting the proper one

I will keep the second one, mainly because of the fact that rarely will I need the extra information that exists on the filename.

If anyone has a better solution though, I am always open to suggestions.