Ravi Sagar | Home | Blog

Blogging with Emacs and Org Mode

Table of Contents

1 Overview

So you are 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
  • Move header up and down: Esc-UP and Esc-Down
  • Increment and decrement header level: Esc-LEFT and Esc-Right
  • Zoom in: C-x C-+
  • Zoom out: C-x C–
  • Default zoom: C-x C-0
  • After one combination of either C-x C-+, C-x C– or C-x C-0 you can press +, - or 0

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


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 lateraa)
  • Reporting: Just insert these lines and press C-c C-c to generate a report anywhere in your file.
Table 1: Clock summary at [2021-09-06 Mon 18:09]
Headline Time
Total time 0:00

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.

Table 2: Clock summary at [2021-01-11 Mon 13:34]
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

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 TODO Excluding subtree from the agenda

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: <2020-04-21 Tue>

To scheduled multiple tasks you can simple insert 2 days like this.

9.5.1 This needs to be done in the morning

<2022-01-01 Sat 04:00>–<2022-01-01 Sat 07:00> <2022-01-01 Sat 09:00>–<2022-01-01 Sat 12:00>

9.6 Deadline DEADLINE: <2020-04-22 Wed>

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 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.

This is a drawer

This is my drawer where I keep my documents.

Store your important but kind of hidden.

To avoid this drawer text from getting exported you can add this in this in your document.

#+OPTIONS: num:nil d:(not "DRAWERNAME")

9.10.1 sub tree

Information inside subtree

9.11 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 Packages

There is a MELPA package repository from where you can install and update your packages. Packages are like modules. You don't have to use MELPA but it is much convenient then installing packages manuallu.

Install a package using command M-x package-install RET ox-reveal RET can be used to install a package.

Package list M-x list-packages RET will take you to a list of packages in the buffer. Just press i on the package name and then press x and it will install the package for you.

MELPA package archive in your init file Modify your init file to use melpa instead of stable becuase you might not find all the packages in stable.

(require 'package)
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/") t)

(add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/") t)

11 Emacs customisations

11.1 Check keybinding

If you want to know if a key binding is used somewhere then simply do C-h k

11.2 Hide menu bar

I use the following configurations to hide/disable to menu bar, scroll bar and tool bar. You don't have to but I like it.

(menu-bar-mode -1)
(toggle-scroll-bar -1)
(tool-bar-mode -1)

11.3 Swap buffer

There is a command window-swap-states to swap the buffer. Which of course you can bind to a key in your init file.

(global-set-key (kbd "<C-return>") 'window-swap-states)

Nice isn't it?

11.4 Show command in the buffer

When showing how emacs or org mode works to someone you may want to show your commands in a buffer. This is super useful and can be done using a mode.

  • M-x package-install command-log-mode: To install the package.
  • M-x command-log-mode: To turn on the mode in the current buffer
  • M-x global-command-log-mode: To turn on the mode in all the buffers
  • M-x clm/open-command-log-buffer: To open the buffer

11.5 Reload emacs configurations without restarting

While your .emacs is open simple run M-x eval-buffer. You can actually do it in any buffer where you want to evaluate the code.

12 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.

13 How to start using Org Mode?

13.1 First install Emacs and then install the org package M-x package-install RET org RET.

13.2 Your best place to learn is https://orgmode.org/

14 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.

14.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'>
<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>
<div class='footer'>Copyright © 2020. Last updated: %C, built with %c</div>"

(defvar ravipro-html-blog-postamble
  "<div class='nav'>
<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>
<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"
            (org-publish-find-title entry project)
            (format-time-string "%Y-%m-%d" (org-publish-find-date entry project))))

(setq org-publish-project-alist
         :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

          :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


          :base-directory "~/ravi.pro/images/"
          :base-extension "png\\|jpg"
          :publishing-directory "/Users/spareuser/projects/ravi.pro/images/"
          :recursive t
          :publishing-function org-publish-attachment

          :base-directory "~/ravi.pro/css/"
          :base-extension "css"
          :publishing-directory "/Users/spareuser/projects/ravi.pro/css/"
          :recursive t
          :publishing-function org-publish-attachment

          :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"))


14.1.1 TODO So let us discuss this piece of code

14.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

14.2.1 Issues you may encounter

  • Sitemap title not updating?: Clear the content of ~/.org-timestamps folder and export again.

14.3 CSS used on my site


    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;

14.4 Host your website

Here are the steps.

  1. 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 project user.gitlab.io and enable the GitLab pages and your website will be published under https://user.gitlab.io
  • Under your group group create a project group.gitlab.io and enable the GitLab pages and your website will be published under https://group.gitlab.io

Make sure pages can be viewed by everyone.

  1. Create a file called .gitlab-ci.yml in your repository root with the following content.
  stage: deploy
    - mkdir .public
    - cp -r * .public
    - mv .public public
      - public
    - 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.

  1. Add CNAME record that points to user.gitlab.io
  2. 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?

15 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.

  1. Set this in your .emacs file.
(setq org-confirm-babel-evaluate nil)
  1. Add this on top of your file, close and open the file again.
# -*- org-confirm-babel-evaluate: nil -*-

16 Open a website in Emacs

Emacs Web Wowser - eww can be used to open sites.

  • M-x-eww then type in the url.

17 Presentations in Emacs

17.1 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.

17.1.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.

17.1.2 Install org-tree-slide package

Just install this packages from the MELPA repository and then let us get started.

17.1.3 How to get started?

Open any org file with headers and then start the presentation using org-tree-slide-mode

17.1.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)

17.1.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

17.1.6 You will love org-tree-slide :) I promise

Cool isn't it?

17.2 Make beautiful web presentations with org-reveal

17.2.1 Install the package.

M-x package-install RET ox-reveal RET

17.2.2 Add this in the org file.

#+REVEAL_ROOT: https://cdn.jsdelivr.net/npm/reveal.js
#+OPTIONS: toc:1 num:nil

17.2.3 Load org-reveal

To load Org-reveal, type M-x load-library, then type ox-reveal.

17.2.4 Export the presentation

You can then export your presentation to an HTML file using C-c C-e R R

17.2.5 Navigate presentation

  • Move forward: space
  • Move backword: S-space
  • Use arrow key to move vertically or horizontally in a the matrix
  • Overview of the slides: o

17.2.6 Set themes

You can also check various themes and use them in your presentation. Check the available themes here: https://revealjs.com/themes/ Use the theme like this.


17.2.7 Images in org-reveal

If you org file has inline images then those will be included in the presentation

17.2.8 Fragmented contents

If you have bullet points which I guess you most likely have then for some of those lists you may want to show them one by one, just like traditional slides. You can do that easily.

#+ATTR_REVEAL: :frag (appear)
- Atlassian Consultant, developer and trainer. Founder of Sparxsys Solution, an Atlassian Consultancy company based in London and Delhi
- Author of Mastering Jira book series and other Jira books
- Certified Professional Jira Administrator
- Certified in Agile Development with Jira Software
- Certified SAFe® 5 Program Consultant

18 Spreadsheets in Org Mode

18.1 Calculate days left

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
<2021-10-31 Sun> Apply for college 92.239803
<2022-10-31 Mon> Major event 457.23980
<2021-01-26 Tue> Republic day -185.76020

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.

18.2 DONE Calculate Total

Start time End time Activity Hours
03 07 App development 4
09 12 App development 3
13 15 Course development 2
16 17 Atlassian Community and support 1
17 18 Daily videos 1
Total     11

18.3 Sorting in tables

Press C-c ^ on the column and select the sort type.

19 How I organise my Org Mode files

main.org: Date involved

  • Project 1

– sub project 1 – sub project 2

  • Project 2

misc.org: No date involved

  • Buy milk
  • Car service

bills.org: Date involved, recurring

  • pay bill 1
  • pay bill 2

tickler.org: Reminders

  • reminder 1
  • reminder 2

inbox.org: All the ideas will go here

  • task 1
  • task 2
  • random idea

journal.org: Writing regular

  • journal entries

20 Good external resources

21 using emacsclient

If you have emacs server running in your init file then you can use emacsclient -nw FILENAME to open any file from another terminal. Use -nw so that emacs open the file in the terminal not the original emacs window where server is running. To see how emacs server works check this file.

22 Custom functions.

22.1 Rename tags.

; You can write a function that check if an entry has "tag1" and if so change it to "tag11":
(defun change-tag (old new)
  (when (member old (org-get-tags))
    (org-toggle-tag new 'on)
    (org-toggle-tag old 'off)
; Now all you have to do is apply that function to each entry that has "tag1". You can do this with org-map-entries:
(defun org-rename-tag (old new)
  (interactive "scurrent tag: \nsnew name: ")
   (lambda () (change-tag old new))
   (format "+%s" old)

Call this with M-x org-rename-tag and it will prompt for the old and new tag names and proceed to change the tags everywhere in the current buffer.

23 Search in org mode

I have lot of TODO items in my agenda files but not all of them requires my attention. So I use priority for those tasks and then search search high priority tasks.

C-c a m
Match: Priority="A"

24 Images in Emacs

24.1 Show Inline images globally

To ensure that the images are shown globally add this code in your init file.

(setq org-startup-with-inline-images t)

24.2 Show Inline images locally

I personally prefer showing the images per file. This can be done by adding on of this in your file.

#+STARTUP: inlineimages
#+STARTUP: noinlineimages

24.3 Toggle inline images

You may also want to toggle the display of inline images. You can do that using org-toggle-inline-images.

24.4 Emacs with ImageMagick

Details here: https://www.gnu.org/software/emacs/manual/html_node/elisp/ImageMagick-Images.html

To check imagemagick support evaluate this express. M-x eval-expression RET (image-type-available-p 'imagemagick) RET

(image-type-available-p 'imagemagick)
(getenv "PATH")

Find imagemagick path

Well it is usually /usr/bin/convert

Tell emacs where imagemagick is if it is not already in the PATH.

(setenv "PATH" (concat (getenv "PATH") ":/usr/bin"))

24.4.1 Emacs won't have ImageMagick as default starting from version 27.1

24.5 Emacs without ImageMagick

So imagemagick is deprecated but emacs can handle image manipulation, at least basic things. To increase/decrease the size of an image place the cursor on the image and run image-increase-size and image-decrease-size. It won't make images responsive but works for now. Now I can use Emacs to present with images if I want.

25 Take screenshot, save images in current directory and insert image link

If you take lot of screenshots then this can be super useful. Add this function in your init file.

(defun my-org-screenshot ()
  "Take a screenshot into a time stamped unique-named file in the
same directory as the org-buffer and insert a link to this file."
  (setq filename
          (concat (buffer-file-name)
                  (format-time-string "%Y%m%d_%H%M%S_")) ) ".png"))
  (call-process "import" nil nil nil filename)
  (insert (concat "[[" filename "]]"))

Now call M-x my-org-screenshot and you can take screenshot and the file will be saved in the directory same as your buffer with timestamp and at the same time it will be inserted as a link as well. Finally using org-display-inline-images the image will be displayed as well. Super cool. Source: https://orgmode.org/worg/org-hacks.html



Thanks Robert Davis for the tip: https://youtu.be/C2ZSa9RshbU