Blogging with Emacs and Org Mode
Table of Contents
- 1. Overview
- 2. Who this blog is for?
- 3. This blog/site is built with Emacs and Org Mode
- 4. What can you learn here on this blog post?
- 5. Come back to this blog post
- 6. Emacs and Org Mode fundamentals
- 7. What is Org Mode?
- 8. What can you do with Org Mode?
- 9. Key features of Org Mode
- 10. Do you need Org Mode?
- 11. How to start using Org Mode?
- 12. Publish a website
- 13. Execute code - Literate Programming
- 14. Open a website in Emacs
- 15. Presentations using Org Mode using Org Tree Slide
- 16. Spreadsheets in Org Mode
- 17. Good external resources
1 Overview
So you ar wondering if Emacs1 can be used to do blogging and at the same time also thinking about why use Org Mode2? Well the answer is simple. I want to keep things simple. Blogging is all about content and I spend lot of time making notes, keeping a list of things I want to do in Org Mode, there are lot of blog I just couldn't write on my Drupal site www.ravisagar.in because it is a bit of a pain to copy, organise and transfer it to a web portal.
With Emacs and Org mode you can just do blogging from your terminal (yes I used Emacs in terminal mode) and I believe I can do it much faster and will be able to share more information quickly whenever I want. Also the other benefit is that with Org mode I can share code snippets that can also be run and evaluated. It is so much fun :)
Update: I started writing this blog post with the intention to help others who may want to write and publish a blog using Emacs and Org Mode but I have kept on adding stuff to this post and it is no longer just for blogging. I have included lot of things in the post related to literate programming, Org Mode fundamentals and I am still adding things here to share my workflow. Enjoy.
2 Who this blog is for?
- You use Emacs
- You use Org mode
- You want to blog
- You want to share content with code
- You like simplicity
3 This blog/site is built with Emacs and Org Mode
I made this site using Emacs of course (otherwise what is the point). Apart from my Drupal sites I have tried using Hugo, Grav, Github pages before, I still have those blogs up and running but I don't plan to update it with more content. Those static site generator where more of an experiment. I personally loved working on Hugo for its simplicity and I was amazed by Grav for its CMS like capabilities (it is still file based).
4 What can you learn here on this blog post?
- Learn how to use Emacs (not an expert level but enough to get you started)
- Learn how to use Org Mode for note taking
- Learn how to use Org Mode for blogging
- Publish yyour blog and host it
The idea of this blog is to create one big (not too big) document that will make it very easy for anyone to install Emacs and start using it.
5 Come back to this blog post
I will keep on updating this blog post with new content. So you may want to come back to this post if you have want to learn more.
6 Emacs and Org Mode fundamentals
6.1 Basic commands
Let us learn the fundamentals first. I also made a video to show these basic commands.
Abbreviations use:
- C is Ctrl key
- M is Meta
Windows - Meta key is Alt Mac - Meta key is Esc
- Close the IDE: C-x C-c
- Save the file: C-x C-s
- Cut: C-w
- Paste: C-y
- Undo: C-_
- Copy: M-w
- Search: C-s
6.2 Split the screen
- Vertical split: C-x-3
- Horizontal split: C-x-2
- Move between windows: C-x-b
- Closing the active window: C-x-0
- Full screen: M-M-M
- Make current window wider: C-x }
- Make current window narrower: C-x {
- Specify the size to make things simpler C-u 40 C-x } or M-40 C-x } 3
- Specify the default size of 4 by doing C-u C-x } 3
- Specify size before the split C-u 40 C-x-3 3
6.3 Tips for making writing experience better
- Insert a link C-c C-l
- Open existing link in the browser, move cursor to the link and pres C-c C-o
- Make the text fit in the window: visual-line-mode
Add this in your .emacs
to enable it by default.
(add-hook 'org-mode-hook 'visual-line-mode)
- Indentation based on the headers: org-indent-mode
Add this in your .emacs
to enable it by default.
(add-hook 'org-mode-hook 'org-indent-mode)
- Insert footnote: C-c C-x f
- Demoting a subtree: M-S-right
- Promoting a subtree: M-S-left
Enjoy
6.4 Macros in Emacs
C-x ( - Start the macro C-x ) - end the macro C-x e - repeat the macro
6.5 Switch between buffers
If you do C-x b
then you can type in the name of the buffer or you can press C-x C-b
it will bring up the list of all the buffers.
However there is another way. You can use C-x <left>
and C-x <right>
as well which is quicker.
6.6 Clock time
You can record time you spent to work on a task.
- Start clock: C-c C-x C-i
- Stop clock: C-c C-x C-o
- Update time interval: C-c C-c (Do that while the cursor is on the time range. I do that a lot because I often add time later )
- Reporting: Just insert these lines and press C-c C-c to generate a report anywhere in your file.
Things are self explanatory. For more details check this page.
6.7 Task that needs to be tracked
6.8 Archive a task
When a task is done you can remove it from the org file by C-c C-x C-a
6.9 Clock table
So you have been logging your time, great. What about reports?
Type M-x org-clock-report
to insert a report.
Headline | Time |
---|---|
Total time | 0:00 |
7 What is Org Mode?
Org-mode is a document editing, formatting, and organizing mode, designed for notes, planning, and authoring within the free software text editor Emacs. Source: Wikipedia.
8 What can you do with Org Mode?
8.1 Literate Programming with Org Babel
To insert a template I use a short <s - <tab>
and it will insert a source block but you can also insert your own block templates.
Insert this in your .emacs file
(add-to-list 'org-structure-template-alist '("g" "#+NAME: fileName ?\n#+BEGIN_SRC groovy :exports code :results output :tangle directory/fileName.groovy \n\n#+END_SRC"))
Now using <g - <tab>
you can quickly insert this groovy specific template. ?
mark is the place where your cursor will be when you insert the template.
For more than one template use the following code.
(add-to-list 'org-structure-template-alist '("g" "#+NAME: fileName ?\n#+BEGIN_SRC groovy :exports code :results output :tangle directory/fileName.groovy \n\n#+END_SRC")) (add-to-list 'org-structure-template-alist '("t" "#+TITLE: ?\n#+DATE: \n#+AUTHOR: "))
8.1.1 Editing source code video
Now this literate programming this is really cool but when you are writing the code within org mode you may not get your autocomplete or snippets working and for a true rich editing experience you may need that. Especially when you need to write a bit more code. Fortunately there is a way of doing that.
Press C-c '
from within your source code block and it will open a new buffer with the body of your source code block and it will respect the language mode that you may have setup. Press C-c '
again and the buffer will close and return to the document. Super cool I know. You can learn more about it here.
8.2 Power of Emacs
8.3 Everything is a text file
9 Key features of Org Mode
9.1 Folding
9.2 States
9.3 Track progress
9.4 Agenda view
Week-agenda (W17): Monday 20 April 2020 W17 misc: Sched.65x: TODO Update Expense sheet spx: Sched.41x: How to un-exclude the issues from a plan? :video::t1719: spx: Sched.41x: Blog about why I like Jira :blog::t1719: spx: Sched.40x: Create a project using a Groovy script: link :video::p912: spx: Sched.40x: Video Create a project using a Groovy script: link :p912:video: spx: Sched.40x: Write a script to create linked issue :video::p912:
Now when you are looking at the agenda you may want to display it for the next 10 days. You can do that by M-10 C-c a a
.
9.4.1 Excluding subtree from the agenda video
Sometimes I do have subtree with dates or TODO
keywords. Those will start appearing in my agenda but I don't want them to appear there. fortunately there is a way.
Just add COMMENT
keyword in front of the subtree and that is it.
COMMENT TODO This will not appear in the agenda.
Cool isn't it?
You can also use C-c ;
or org-toggle-comment
to add or remove the COMMENT keyword.
9.5 TODO Schedule tasks SCHEDULED:
9.6 Deadline DEADLINE:
9.7 Org Capture
9.8 Refile
9.9 Spell check
M-$ on the word and it will give you suggestions with numbers. Just press the number if you want to use the suggestion.
9.10 TODO Drawer video
You can store additional information related to an entry and you can do that with the help of drawer.
You can insert then using org-insert-drawer
. The format is like this.
:DRAWERNAME: This is a drawer :END:
To avoid this drawer text from getting exported you can add this in this in your document.
#+OPTIONS: num:nil d:(not "DRAWERNAME")
9.11 TODO Exclude tags are awesome video
It is possible that there are certain headings in your document that you don't want to be exported. You can add this on top of your document.
#+EXCLUDE_TAGS: noexport
Now any heading with noexport
will not get exported but will still be there in your document for you to finish.
9.12 Narrowing and widening
Let us say you are working on a big document but you want to focus on a specific heading. It may be useful when you are presenting a document as a presentation but within Emacs.
- Narrow: C-x n s
- Widen: C-x n w
10 Do you need Org Mode?
Short answer is yes but don't expect immediate results. You need to spend time learning it. It is mostly for geeky people who are comfortable using terminal. If you are not used to typing commands then don't bother.
11 How to start using Org Mode?
11.1 First install Emacs and then install the org package M-x package-install RET org RET
.
11.2 Your best place to learn is https://orgmode.org/
12 Publish a website
So are you ready to launch a website using Org mode? Great. Let us begin. First you need to modify your Emacs configuration file - .emacs
for publishing to work.
12.1 Snippet of my .emacs file responsible for publishing this blog
The following code make sure that it will read the *.org files in a specific directory and it will generate HTML out of it and also add few other things like header, footer and css.
; Publishing using Org-mode ;(add-to-list 'load-path "~/.emacs.d/ox-rss.el") (require 'ox-rss) (defvar ravipro-html-head "<link rel='stylesheet' href='css/style.css' type='text/css'/>") (defvar ravipro-html-blog-head "<link rel='stylesheet' href='../css/style.css' type='text/css'/>") (defvar ravipro-html-preamble "<div class='preamble'><a href='/'>Ravi Sagar</a> | <a href='/'>Home</a> | <a href='blog/blog.html'>Blog</a></div>") (defvar ravipro-html-blog-preamble "<div class='preamble'><a href='/'>Ravi Sagar</a> | <a href='/'>Home</a> | <a href='../blog/blog.html'>Blog</a></div>") (defvar ravipro-html-postamble "<div class='nav'> <ul> <li><a href='/'>Home</a></li> <li><a href='sitemap.html'>Sitemap</a></li> <li><a href='blog/blog.html'>Blogs</a></li> <li><a href='http://twitter.com/ravisagar'>Twitter</a></li> </ul> </div> <div class='footer'>Copyright © 2020. Last updated: %C, built with %c</div>" ) (defvar ravipro-html-blog-postamble "<div class='nav'> <ul> <li><a href='/'>Home</a></li> <li><a href='../sitemap.html'>Sitemap</a></li> <li><a href='../blog/blog.html'>Blogs</a></li> <li><a href='http://twitter.com/ravisagar'>Twitter</a></li> </ul> </div> <div class='footer'>Copyright © 2020. Created %d, Last updated %C, built with %c</div>" ) (defun ravipro-format-entry (entry style project) (format "[[file:%s][%s]] --- %s" entry (org-publish-find-title entry project) (format-time-string "%Y-%m-%d" (org-publish-find-date entry project)))) (setq org-publish-project-alist `( ("home" :base-directory "~/ravi.pro/" :publishing-directory "/Users/spareuser/projects/ravi.pro/" :recursive t :exclude "level-.*\\|.*\.draft\.org" :publishing-function org-html-publish-to-html :auto-sitemap t :sitemap-filename "sitemap.org" :sitemap-title "Sitemap" :sitemap-sort-files anti-chronologically :with-toc nil :html-head ,ravipro-html-head :html-link-up "/" :html-link-home "/" :html-preamble ,ravipro-html-preamble :html-postamble ,ravipro-html-postamble ) ("blog" :base-directory "~/ravi.pro/blog/" :publishing-directory "/Users/spareuser/projects/ravi.pro/blog/" :exclude "level-.*\\|.*\.draft\.org" :publishing-function org-html-publish-to-html :auto-sitemap t :sitemap-filename "blog.org" :sitemap-title "All Blogs" :sitemap-sort-files anti-chronologically :sitemap-format-entry ravipro-format-entry :html-head ,ravipro-html-blog-head :html-link-up "/" :html-link-home "/" :html-preamble ,ravipro-html-blog-preamble :html-postamble ,ravipro-html-blog-postamble ) ("images" :base-directory "~/ravi.pro/images/" :base-extension "png\\|jpg" :publishing-directory "/Users/spareuser/projects/ravi.pro/images/" :recursive t :publishing-function org-publish-attachment ) ("css" :base-directory "~/ravi.pro/css/" :base-extension "css" :publishing-directory "/Users/spareuser/projects/ravi.pro/css/" :recursive t :publishing-function org-publish-attachment ) ("rss" :base-directory "~/ravi.pro/" :publishing-directory "/Users/spareuser/projects/ravi.pro/" :base-extension "org" :html-link-home "https://www.ravi.pro/" :html-link-use-abs-url t :rss-extension "xml" :publishing-function (org-rss-publish-to-rss) :recursive t ) ("website" :components ("home" "blog" "images" "css")) ))
12.1.1 TODO So let us discuss this piece of code
12.2 Publishing commands
These commands will be used to publish the site into HTML format to a specific location that you set above in the .emacs
file.
- Publish: M-x org-publish
- Shortcut: C-c C-e P x PROJECTNAME
- Force publish (all files): C-u M-x org-publish
12.2.1 Issues you may encounter
- Sitemap title not updating?: Clear the content of
~/.org-timestamps
folder and export again.
12.3 CSS used on my site
body{ max-width: 70%; margin: auto; font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; color: #222222; } .nav { background: #aeaeae; padding: 10px; } .preamble { background: #330000; padding: 10px; color: #ffffff; } .preamble a:visited { color: #ffffff; } .preamble a:link { color: #ffffff; }
12.4 Host your website
Here are the steps.
- First setup the repository with the correct name.
There are 2 main ways of doing it on GitLab.com. Refer to this page.
- Under your username
user
create a projectuser.gitlab.io
and enable the GitLab pages and your website will be published underhttps://user.gitlab.io
- Under your group
group
create a projectgroup.gitlab.io
and enable the GitLab pages and your website will be published underhttps://group.gitlab.io
Make sure pages can be viewed by everyone.
- Create a file called
.gitlab-ci.yml
in your repository root with the following content.
pages: stage: deploy script: - mkdir .public - cp -r * .public - mv .public public artifacts: paths: - public only: - master
I use GitLab.com to host my site. I manage the directory where I publish my HTML in my Git repository on GitLab. I also made a video about it.
- Add CNAME record that points to
user.gitlab.io
- Verify your domain
Go to your repository settings and add both example.com
and www.example.com
. You will then get a TXT record that you need to add for your domain. Wait for the verification to finish and you now have a site hosted for free on GitLab. Cool isn't it?
13 Execute code - Literate Programming
You can insert code snippets in your document.
- C-c C-c – Execute the code
When you export to HTML you will be asked to export all the code blocks one by one. However you can execute them without your confirmation.
Two ways to do it.
- Set this in your
.emacs
file.
(setq org-confirm-babel-evaluate nil)
- Add this on top of your file, close and open the file again.
# -*- org-confirm-babel-evaluate: nil -*-
14 Open a website in Emacs
Emacs Web Wowser - eww can be used to open sites.
- M-x-eww then type in the url.
15 Presentations using Org Mode using Org Tree Slide
Now earlier in this document we talked about Narrowing and Widening which is great and works wonderfully well but not only focussed work but also for presentations.
15.1 Presentations in Org Mode
There are various packages available for making proper presentations and I will dive into them as well but in case you are like me and want to present within org file that can be edited live there is a nice way of doing it using org-tree-slide
package.
15.2 Install org-tree-slide package
Just install this packages from the MELPA repository and then let us get started.
15.3 How to get started?
Open any org file with headers and then start the presentation using org-tree-slide-mode
15.4 Navigate slides
How to navigate? Well if you are on mac then C-<
and C->
will not work I think but you can always add your keybindings in the emacs configuration file.
(with-eval-after-load "org-tree-slide" (define-key org-tree-slide-mode-map (kbd "<f5>") 'org-tree-slide-move-previous-tree) (define-key org-tree-slide-mode-map (kbd "<f6>") 'org-tree-slide-move-next-tree) )
15.5 Profiles
There are profiles that you can turn on before you start the presentation.
- M-x org-tree-slide-simple-profile
Display slides without header
- M-x org-tree-slide-presentation-profile
Display slides with header, default profile
- M-x org-tree-slide-narrowing-control-profile
Present only subtrees with TODO
15.6 You will love org-tree-slide :) I promise
Cool isn't it?
16 Spreadsheets in Org Mode
We discussed briefly how to create a table but we can do more with them like some calculations. Let us take a look at a simple example. Track days until
End date | Event | Days left |
---|---|---|
Apply for college | 296.48726 | |
Major event | 661.48726 | |
Repulic day | 18.487257 |
You have to use this #+END_SRC $3=(date($1) - date(now()))
, you can do lot of other things but I wanted to give you a quick idea about how to get started with calculations.
17 Good external resources
17.1 TODO Read this article: https://emacs.cafe/emacs/orgmode/gtd/2017/06/30/orgmode-gtd.html
Footnotes:
The link to Emacs: https://www.gnu.org/software/emacs/
Org Mode: https://orgmode.org/
Thanks Robert Davis for the tip: https://youtu.be/C2ZSa9RshbU