From 2094c32421e9eabc51d1eb467df9edae202ece4a Mon Sep 17 00:00:00 2001 From: Elia el Lazkani Date: Sat, 22 Aug 2020 18:47:30 +0200 Subject: [PATCH] Adding a new blog post, emacs and org-mode --- posts/text-editors/emacs-and-org-mode.rst | 241 ++++++++++++++++++++++ 1 file changed, 241 insertions(+) create mode 100644 posts/text-editors/emacs-and-org-mode.rst diff --git a/posts/text-editors/emacs-and-org-mode.rst b/posts/text-editors/emacs-and-org-mode.rst new file mode 100644 index 0000000..6aba920 --- /dev/null +++ b/posts/text-editors/emacs-and-org-mode.rst @@ -0,0 +1,241 @@ +.. title: Emacs and Org-mode +.. date: 2020-08-22 +.. slug: emacs-and-org-mode +.. updated: 2020-08-22 +.. status: published +.. tags: emacs, org-mode, configuration, +.. category: text-editors +.. authors: Elia el Lazkani +.. description: I ditched VSCode and moved back to Emacs... You heard me ! +.. type: text + +I have recently found out, late I know, that the *VSCode* distribution of the so called *Code - OSS* is exactly that; a distribution. + +Let me make it clear, the *VSCode* binaries you download from **Microsoft** has an upstream the **GitHub repository*** named `VSCode `_ but in fact is not exactly the same code. +**Microsoft** has already added a few gifts for you, including *telemetry*, not cool huh ?! +Well, they tell you this in the documentation, urrrmmm `somewhere `_. + +At the same time, I was giving *Jupyter Notebook* a try. I worked on my previous post in it before writing down the final result as a blog post. +But at the back of my mind, there was always `Org-mode `_. + +Putting one and one together, you've guessed it. I have moved to *Emacs*... again... for the umm I can't remember time. +But this time, it is different ! I hope... + +.. TEASER_END + +Back story +========== + +I was using *Jupyter Notebooks* as a way to write down notes. Organize things. +I had a work around the *output* and was able to clean it. +But let's face it, it might work but it is designed more towards other goals. +I want to write notes and the best way to work with notes is to keep in the text, literally. +I found a *VSCode* extension that can handle *Org-mode* in some capacity (I haven't tested it) so I decided to switch to *Emacs* and keep the extention as a backup. + +Emacs Distribution of Doom +========================== + +Haha ! Very funny, I know. I went with `Doom `_. +Why? You may ask. I don't really have a good answer for you except the following. + + * I didn't want to start from scratch, I wanted something with batteries included. + * At the same time, I've tried *Doom* before and I like how it does things. + It is logical to me while at the same time very configurable. + * I was able to get up and running very quickly. Granted, my needs are few. + * I got *Python* and *Golang* auto-completion and *evil* mode. I'm good to go ! + +Now let's dig down to my main focus here. Sure I switched editors but it was for a reason; **Org-mode**. + +Org-mode Configuration +====================== + +I will be talking about two different configuartion options here. +I am new to emacs so I will try to explain everything. + +The two options are related to the difference between a *vanilla* configuration and *Doom*'s version of the configuration. +The differences are minor but they are worth talking about. + +New Org File +------------ + +If you've used *Org-mode* before and created *org files*, you already know that you need to set a few values at the top of the file. These include the *title*, *author*, *description* and a different other values to change setting and/or behavior. + +It is a bit of a manual labor to write these few lines at the beginning of every file. I wanted to automate that. So I got inspiration from `shakthimaan `_. + +I used his method to create a small ``define-skeleton`` for a header. +It looks something like this. + +.. code:: lisp + + (define-skeleton generate-new-header-org + "Prompt for title, description and tags" + nil + '(setq title (skeleton-read "Title: ")) + '(setq author (skeleton-read "Author: ")) + '(setq description (skeleton-read "Description: ")) + '(setq tags (skeleton-read "tags: ")) + "#+TITLE: " title \n + "#+AUTHOR: " author \n + "#+DESCRIPTION: " description \n + "#+TAGS: " tags \n + ) + +You can use this later with ``M-x`` + ``genrate-new-header-org``. + +.. note:: + + ``M-x`` is the **Meta** key and **x** combination. + Your **Meta** key can differ between the **Alt** on *Linux* and **Command** on *Mac OS X*. + + ``M-x`` will open a prompt for you to write in. Write the name you gave the skeleton, in this case it is ``generate-new-header-org`` and then hit the *Return*. + +New Task +-------- + +`shakthimaan `_ already created something for this. It looks like the following. + +.. code:: lisp + + ;; Create a new skeleton to generate a new =Task= + (define-skeleton insert-org-entry + "Prompt for task, estimate and category" + nil + '(setq task (skeleton-read "Task: ")) + '(setq estimate (skeleton-read "Estimate: ")) + '(setq owner (skeleton-read "Owner: ")) + '(setq category (skeleton-read "Category: ")) + '(setq timestamp (format-time-string "%s")) + "** " task \n + ":PROPERTIES:" \n + ":ESTIMATED: " estimate \n + ":ACTUAL:" \n + ":OWNER: " owner \n + ":ID: " category "." timestamp \n + ":TASKID: " category "." timestamp \n + ":END:") + +This can also be used like the one above with ``M-x`` + ``insert-org-entry``. + +Doom specific configuration +--------------------------- + +Whatever defined so far should work if you just add it to your configuration but if you use *Doom* it would a nice touch to integrate it with the workflow. + +In ``~/.doom.d/config.el``, wrap the previous definitions with ``(after! org)``. +It's a nice touch to add these skeletons after *Org-mode* has loaded. + +.. code:: lisp + + (after! org + ;; Create a skeleton to generate header org + (define-skeleton generate-new-header-org + "Prompt for title, description and tags" + nil + '(setq title (skeleton-read "Title: ")) + '(setq author (skeleton-read "Author: ")) + '(setq description (skeleton-read "Description: ")) + '(setq tags (skeleton-read "tags: ")) + "#+TITLE: " title \n + "#+AUTHOR: " author \n + "#+DESCRIPTION: " description \n + "#+TAGS: " tags \n) + + ;; Create a new skeleton to generate a new =Task= + (define-skeleton insert-org-entry + "Prompt for task, estimate and category" + nil + '(setq task (skeleton-read "Task: ")) + '(setq estimate (skeleton-read "Estimate: ")) + '(setq owner (skeleton-read "Owner: ")) + '(setq category (skeleton-read "Category: ")) + '(setq timestamp (format-time-string "%s")) + "** " task \n + ":PROPERTIES:" \n + ":ESTIMATED: " estimate \n + ":ACTUAL:" \n + ":OWNER: " owner \n + ":ID: " category "." timestamp \n + ":TASKID: " category "." timestamp \n + ":END:") + ) + + +.. warning:: + + If you modify any file in ``~/.doom.d/``, do not forget to run ``doom sync`` and ``doom doctor`` to update and check your configuration respectively. + +Final touches +------------- + +I wanted to add it to the menu system that comes with *Doom* so I included the following in my ``(after! ...)`` block. + +.. code:: lisp + + ;; Add keybindings with the leader menu for everything above + (map! :map org-mode-map + (:leader + (:prefix ("m", "+") + :n :desc "Generate New Header Org" "G" 'generate-new-header-org + :n :desc "New Task Entry" "N" 'insert-org-entry + )) + ) + +Making the final configuration look like the following. + +.. code:: lisp + + (after! org + ;; Create a skeleton to generate header org + (define-skeleton generate-new-header-org + "Prompt for title, description and tags" + nil + '(setq title (skeleton-read "Title: ")) + '(setq author (skeleton-read "Author: ")) + '(setq description (skeleton-read "Description: ")) + '(setq tags (skeleton-read "tags: ")) + "#+TITLE: " title \n + "#+AUTHOR: " author \n + "#+DESCRIPTION: " description \n + "#+TAGS: " tags \n) + + ;; Create a new skeleton to generate a new =Task= + (define-skeleton insert-org-entry + "Prompt for task, estimate and category" + nil + '(setq task (skeleton-read "Task: ")) + '(setq estimate (skeleton-read "Estimate: ")) + '(setq owner (skeleton-read "Owner: ")) + '(setq category (skeleton-read "Category: ")) + '(setq timestamp (format-time-string "%s")) + "** " task \n + ":PROPERTIES:" \n + ":ESTIMATED: " estimate \n + ":ACTUAL:" \n + ":OWNER: " owner \n + ":ID: " category "." timestamp \n + ":TASKID: " category "." timestamp \n + ":END:") + + (map! :map org-mode-map + (:leader + (:prefix ("m", "+") + :n :desc "Generate New Header Org" "G" 'generate-new-header-org + :n :desc "New Task Entry" "N" 'insert-org-entry + ))) + ) + +What do I do now ? +================== + +You might be asking yourself at this point, what does this all mean ? +What do I do with this ? Where do I go ? + +Well here's the thing. You find yourself wanting to create a new *org file*. +You do so in emacs and follow it with ``M-x`` + ``generate-new-header-org`` (or ``SPC m G`` in **Doom**). *Emacs* will ask you a few questions in the bottom left corner and once you answer then, your header should be all set. + +You can follow that with ``M-x`` + ``insert-org-entry`` (or ``SPC m N``) to generate a task. This will also ask you for input in the bottom left corner. + +Conclusion +========== + +This should help me pick up the usage of *Org-mode* faster. It is also a good idea if you've already configured your *Emacs* to read all your *org file* for a wider **agenda** view.