Productivity Overview

My second most popular post ever describes my Emacs Writing Setup. (My most popular post, if you’re interested, is this one.)

I wrote five novels and about thirty short stories using the method described in my Emacs Writing Setup, all the while experimenting with other methods. For example, I replicated some Scrivener features in Emacs and wrote about them here.

But over the past year all this has changed. So much so that I’m rewriting my Emacs Writing Setup from scratch.

So what’s changed? Briefly, I’ve started using org-roam and Doom Emacs for my writing flow. This has had a knock on effect for my productivity flow in general.

I think that I’m a productive person. I’m an assistant head teacher. I’ve had 8 novels and around 70 short stories short stories published. I maintain three blogs. I play jazz piano, accordion and baritone horn and am a member of two bands. Most importantly I’m a husband, carer and father to two children.

My two secrets? I watch very little TV and I rely heavily on productivity systems. I think if you’re not using a system then you’re not meeting your full potential.

The systems I use are GTD and Zettelkasten. I’ve experimented with others, but these are the two that best match my needs and personality.

I’ve also experimented with various software applications over the years. I’ve yet to find one piece of software that meets all my needs, although Emacs comes close. If I were to work solely on a laptop, that’s all I would use, but like most people I also rely on a phone and browser.

Orgzly and beorg do a good job of replicating the Emacs experience on a phone, but Emacs without a proper keyboard is always unsatisfying. And, as yet, I’ve not found a satisfactory way of using Emacs via a browser.

So my current productivity system relies on three ‘applications’

  • Emacs
  • Evernote
  • Notebook and pen (I use Leuchtturm1917 notebooks and Uniball Jetstream pens for preference)

I use Emacs for most things, principally org-mode for writing and org-roam for Zettelkasten

Why do I use Evernote when I have Emacs? Remember, Zettelkasten is a tool for thinking, it’s not a reference tool. One of the principles of Zettelkasten is that you should separate your notes from your reference materials.

Evernote is ideal for reference, it’s also more suited for phone and browser access. The newly added Evernote Tasks feature goes some way to replicating org-agenda. Okay, it’s got a long way to go to match Emacs but I can live with it for the convenience. (I experimented with Todoist for a while before Evernote tasks came out. I liked Todoist so much I almost feel guilty for not using it. It’s an excellent piece of software, but I like to have all my to dos in one place)

Finally, I use a notebook for ideas and thinking things through.

As word documents are the de facto standard in the publishing world , I still use LibreOffice Writer for submissions and editing, but I would say that I spend 99% of my time on Emacs, Evernote and in my Notebook.

This series of posts describe how I use these Emacs, Evernote and my notepad to implement GTD and Zettelkasten, particularly to support my writing process. As I don’t have the patience to watch videos, as I’m not interested in personal anecdotes or dubious research to support self evident points I won’t be including any of those things here. I will include How Tos and config files for those who are interested.

If there’s anything missing, let me know.

Productivity 2021

My second most popular post ever describes my Emacs Writing Setup. (My most popular post, if you’re interested, is this one.)

I wrote five novels and about thirty short stories using the method described in my Emacs Writing Setup, all the while experimenting with other methods. For example, I replicated some Scrivener features in Emacs and wrote about them here.

But over the past year all this has changed. So much so that I’m rewriting my Emacs Writing Setup from scratch.

So what’s changed? Briefly, I’ve started using Zettelkasten, org-roam and Doom Emacs for my writing flow. This has had a knock on effect for my productivity flow in general.

Over the next few months I’ll be going over my new set up. Let me know what you think.

You’re using folders and tags the wrong way round

According to Ian Small, CEO of Evernote, only 5% of Evernote users use tags. Evernote is not the only application that uses tags and folders, and I suspect the picture is similar in other applications. Most users rely on folders alone to categorize their work. I can understand this. Everyone has used paper folders in real life, the folders in applications replicate this experience.

However I think tagging is better, the reason being that although a note can only be in one folder, it can have more than one tag.

Here’s an example. Suppose you have personal notes and work notes. Some of those notes are just regular notes, some notes outline projects. You could tag your notes as follows:

  • Holiday (personal, project)
  • Shopping (personal)
  • User Manual (work, project)
  • Presentation (work)

Tagging like this gives you more flexibility. You can now filter for all of your projects, or filter for work projects only. By adding additional tags for things such as year 2021, 2022 you can then find, for example, all the personal projects you started in 2021.  Tagging gives your searches a granularity you don’t get by using folders.

Does that mean folders are no use? No. Folders are useful when something can only be on one state. A good example is :

  • Todo
  • In Progress
  • Done

You can set up those three folders and move notes between them. This is the opposite of the commonly recommended practice that you tag work with Todos.

Why are folders better? Because notes can only be in one folder at a time. It’s possible to accidentally tag a note as both Todo and Done. There’s also something quite satisfying about dragging a note from the In Progress to the Done folder…

What if you want to separate your work and personal to-dos? There are two ways. You can go to the Todo folder and filter by work or personal tags. Or it might be easier just to have two sets of folders

  • Work Todo
  • Work in Progress

And

  • Personal Todo
  • Personal in progress

Does it matter if you’re using folders and tags the wrong way round? Of course not. If you can find the right note at the right time, your system is fine. My suggestion is that using tags correctly adds flexibility.

Java Course 3: Random Numbers and Rounding

Random Numbers

Math.random() returns a random double between 0 and <1. Examples are 0.3332, 0.77777779 and 0.1113

To find a random number between 1 and 100, you’d need to do something like this:

double num = Math.random()*100;
int ran = (int)num+1;
System.out.println(ran);

Rounding and Formatting Decimals

double d = 3122.656774;
double roundUp = Math.round(d);
System.out.println(roundUp);

//Roundup to two decimal places
double roundUp2dp = Math.round(d*100)/100.0;
System.out.println(roundUp2dp);

//Formatting a number
//Note that the output is a string
DecimalFormat f = new DecimalFormat("#,###.00");
System.out.println(f.format(d));

Sample Formats

PatternNumberFormatted
###.###123.456123.456
###.#123.456123.5
###,###.##123456.789123,456.79
000.###9.95009.95
##0.###0.950.95

Exercise: Fahrenheit to Celsius

Here are the formulas to convert from Fahrenheit to Celsius and back again.

  • °F to °C: Deduct 32, then multiply by 5, then divide by 9
  • °C to °F: Multiply by 9, then divide by 5, then add 32
  1. Write a program to convert Fahrenheit to Celsius. Use the test data below to check your program.
  2. Now write a program to convert Celsius to Fahrenheit. Again, use the test data to check your program.

Test Data

CF
032
1254
100212
-327
-180
-23-10

Java Course 2: Types

Integers

// declare variables
int x;
int y;

// Instantiate Scanner
Scanner scan = new Scanner(System.in);

// Perform operation
System.out.println("Enter x?");
x = scan.nextInt();
System.out.println("Enter y?");
y = scan.nextInt();
System.out.println("x x y ="+ x*y);

Casting and Converting

Java is a statically, strongly typed language. You have to declare variable types before you use them (statically typed) and once declared, the variables cannot hold another type.

But sometimes you need to change the type. For example, in the code

int i =4;
System.out.println(i);

System.out.println(i) converts the int i into a String before printing out.

You can make an explicit conversion from int to String as follows

int i =4;
String s = Integer.toString(i);
System.out.println(s);

You can covert Double, Float etc to Strings similarly.

To convert the other way, e.g. from a String to an integer use the following

String s = "34"
int i = Integer.parseInt(s);

The fact that you can’t simply use i.toString() is an interesting one and part of a big debate about the way Java is put together. Briefly, Java doesn’t treat types like int and double as classes. That means you have to put them in a class wrapper when you want to perform some operations on them. Languages such as Scala treat all types as classes.

The following code will print out int c as a number and a char, depending on cast.

int c = 67;
System.out.println(c);
System.out.println((char)c);

Exercise: operations on int and double

  1. Write a program with two variables, length and width, that outputs the perimeter of a rectangle. Test it with length = 5 and width = 4.
  2. At the time of writing, the exchange rate for pounds to euros is 1 GBP = 1.19984 Euros. Write a program that will convert pounds to euros. Test it using the data GBP4.50
  3. Now write a program to convert euros to pounds. Test it using the data Euro 7.40
  4. Prompt the user to input a number. Output the square of that number.
  5. Prompt the user to input two numbers. Output the average of those two numbers.
  6. Prompt the user to input three numbers. Output the sum and the average of those three numbers.
  7. Assume pi = 3.1415. Prompt the user to input the radius of a circle. Output the circumference and the diameter of that circle

Good Practice

What’s the purpose of the following two code snippets? Which is better programming practice? Give some reasons why.

double x = 35.51*1.17;
System.out.println(x);

or

double pounds = 35.51;
double euroRate = 1.17;
double euros = pounds * euroRate;

System.out.println("£"+ pounds + " = " + euros + " euros");
System.out.println("at an rate of "+ euroRate + " euros to the pound");

Java Course 1: Input Output

The basic Java program is called a class.  A class is much more than a program, you’ll see why as we go on.

Classes contain methods, which are a little like functions in other languages.  The first function to run is called main().  You will notice it is written

public void main(String [] args)

I’ll explain what those other words mean later on.

Every part of a java program is contained in a block – surrounded by {}

Here is a basic java program.  See if you can run it.  Note the use of escape characters when printing.  Notice that \n gives a new line and \" literally prints "

public class JavaApplication1 {

    public static void main(String[] args) {
       System.out.println("This is really \n... \"groovy!\"");
    }
}

Be careful typing a backslash in Java. It indicates that the next character will be a special code. Be especially careful when writing file paths if you’re a Windows user. Follow the Apple/Linux pattern and use forward slashes, e.g. “C:/Java/Spoons”

Escape SequenceCharacter
\nnewline
\ttab
\bbackspace
\fform feed
\nreturn
\”” (double quote)
\’‘ (single quote)
\\\ (back slash)
\uDDDDUnicode character (DDDD is four hex digits)

Here’s how you read in text. Notice the import scanner line at the beginning.

import java.util.Scanner;

public class JavaApplication1 {

    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        System.out.println("Enter your name");
        String s = scan.nextLine();
        System.out.println("Hello " + s);
    }

Questions

  1. Print the message “I \u2665 Java!”
  2. Look up the the unicode for pi, and use that to print the formula for the circumference of a circle, C=2πr.
  3. Prompt the user to input their name and age. Output a message of the form “Hello (name). You are (age) years old.”
  4. Prompt the user to input first their forename and then their surname. Output their name in the format surname, forename.
  5. Use tabs to print out the following table. (Don’t include the borders)
JohnSmith32
JillGreen35
JackBlack22

Computer Science Supercurriculum

Thinking of studying Computer Science at university?

Top universities aren’t just interested in what you’re doing at school, they want to know about all the extra things you’re doing: what they call the supercurriculum.

This page gives some suggestions on how you can add depth to your studies.

Of course,  you don’t need to be applying to university in order to follow these suggestions.  Anyone with an interest in computers should find this list useful.

Get Coding

If you don’t want to be a better coder you really need to consider if Computer Science is the subject for you. If you do want to be a better coder, here are some ways to improve your skills

Should I Learn another Programming Language?

Yes… but only if you’re really confident with your first language. It’s a good idea to learn a language that does things in a completely different way. Learning a functional language such as Haskell will give you a completely different take on programming. You can get a taste for Haskell here on my blog

Linux

Have you tried the Linux Operating System? There are plenty of websites that will explain the benefits of Linux and will get you started using it, but first you’ll need to get hold of a copy.

VirtualBox is free software that lets you run other operating systems. Ubuntu is a popular Linux distribution  with lots of support.

There are lots of tutorials online showing you how to run Linux on your Windows machine using VirtualBox. Here’s one example: https://itsfoss.com/install-linux-in-virtualbox/

Reading List

Computer books can be expensive. You could try asking your school librarian to order a copy.

  • The Code Book by Simon Singh
  • Learn Python 3 the Hard Way by Zed A Shaw
  • Gödel, Escher, Bach by Douglas Hofstadter
  • Seventeen Equations that Changed the World by Ian Stewart
  • Linguistics Made Easy by Jean Aitchison
  • The Pragmatic Programmer by David Thomas and Andrew Hunt

ibuffer changed my life

I wanted a quick way to delete all the buffers that can accumulate in an Emacs session. A quick search threw up this post by Martin Owen.

It turned out all I needed was ibuffer mode. ibuffer has a toggle command which selects all unselected buffers.

But that’s not all. ibuffer will group your buffers by type, just like in the featured image for this post. It also comes with a range of commands for filtering buffers. Here are my five favourite commands:

  1. t to toggle files selected
  2. / . to filter by extensions
  3. / p to remove top level filter
  4. * h Mark all help buffers
  5. * s Mark all *special* buffers

and here’s my set up: I’ve basically just adapted Martin’s.

(global-set-key (kbd "C-x C-b") 'ibuffer) ; instead of buffer-list
(setq ibuffer-expert t) ; stop yes no prompt on delete

 (setq ibuffer-saved-filter-groups
	  (quote (("default"
		   ("dired" (mode . dired-mode))
		   ("org" (mode . org-mode))
		    ("magit" (name . "^magit"))
		   ("planner" (or
				(name . "^\\*Calendar\\*$")
				(name . "^\\*Org Agenda\\*")))
		   ("emacs" (or
			     (name . "^\\*scratch\\*$")
			     (name . "^\\*Messages\\*$")))))))

(add-hook 'ibuffer-mode-hook
	  (lambda ()
	    (ibuffer-switch-to-saved-filter-groups "default")))

It took me about ten minutes to do all the above from start to finish. Ten minutes well spent, I say.

Pattern Matching: pcase

Haskell allows pattern matching. The following function counts one, two or many objects

simpleCount 1 = "One"
simpleCount 2 = "Two"
simpleCount _ = "Many"

You can use pattern matching to set base cases in recursive functions.

factorial 0 = 1
factorial n = n * factorial (n-1)

Haskell also allows guards. This if statement checks if someone is old enough to drive in the UK

canDrive x = if x<18 then  "Too young to drive" else "Old enough to drive"

Here it is using guards:

canDrive x
          | x<18 = "Too young to drive"       |
          | otherwise = "Old enough to drive" |

pcase

Emacs Lisp offers similar functionality with the pcase macro. It took me some time to understand the documentation, so here are few examples to get you going. They only scratch the surface, make sure you go back and read up properly afterwards.

(defun simple-count (x)
  (pcase x
    (1 "one")
    (2 "two")
    (_ "many")))

(mapcar #'simple-count '(1 2 5))
=> ("one" "two" "many")

Note that _ is used for the don’t care or wildcard case, rather than the more traditional t.

(defun can-drive (x)
  (pcase x
    ((guard (< x 18)) "Too young to drive")
    (_ "Old enough to drive")))

(can-drive 12)
=> "Too young to drive"

The following converts a test mark into a grade. Note the use of and to evaluate (pred stringp). If non nil, it binds x to msg. In other words, pcase can distinguish between marks and teacher comments.

(defun student-grade (x)
  (pcase x
    ((and (pred stringp) msg) msg)
    ((guard (< x 10)) "Fail")
    ((guard (< x 20)) "C")
    ((guard (< x 30)) "B")
    (_ "A")))

(mapcar #'student-grade '("Absent" 23 12 "off roll" 9 35))
=> ("Absent" "B" "C" "off roll" "Fail" "A")

Take a look at this example from the documentation. Again, it uses and to evaluate (pred stringp). If non nil, it binds x to msg.

So, if x is a string, print it; if x is a recognised symbol, print the associated message; otherwise print unknown return code.

(defun my-errors (x)
  (pcase x
    ;; string
    ((and (pred stringp) msg)
     (message "%s" msg))
    ;; symbol
    ('success       (message "Done!"))
    ('would-block   (message "Sorry, can't do it now"))
    ('read-only     (message "The shmliblick is read-only"))
    ('access-denied (message "You do not have the needed rights"))
    ;; default
    (code           (message "Unknown return code %S" code))))

(mapcar #'my-errors '(1 read-only "hello"))
=> ("Unknown return code 1" "The shmliblick is read-only" "hello")

Really Simple Scrivener Mode

Here’s a screenshot of a really simple Scrivener type view for org mode files. I set this up following my simple sidebar set up.

Scriv Sample

I’ve copied the code below (I’ve also joined the 21st Century and started uploading code to GitHub)

The code is actually very simple. To make notes appear in a side window, simply put the letters TR (for top right), BR (for bottom right) or HD (for heading) at the start of a title and then call org-tree-to-indirect-buffer on those headings. I’ve added a key binding to M-s i to make this easy. I like to have certain notes always visible while I’m typing, this system allows me to vary just which notes they are.

And that’s it. Very simple, but I’ve found this very useful when writing.

(defun my-sidebars()
  (setq fit-window-to-buffer-horizontally t)
  (setq window-resize-pixelwise t)

  (setq display-buffer-alist
        `(("\\*Occur\\*" display-buffer-in-side-window
           (side . left) (slot . 0)
           (window-width . fit-window-to-buffer)
           (preserve-size . (t . nil)) 
           (window-parameters . ((no-delete-other-windows . t))))
          (".*\\.org-HD." display-buffer-in-side-window
           (side . top) (slot . 0) 
           (preserve-size . (t . nil)) 
           (window-parameters . ((no-delete-other-windows . t))))
          (".*\\.org-TR." display-buffer-in-side-window
           (side . right) (slot . -1) 
           (preserve-size . (t . nil)) 
           (window-parameters . ((no-delete-other-windows . t))))
          (".*\\.org-BR." display-buffer-in-side-window
           (side . right) (slot . 1) 
           (preserve-size . (t . nil)) 
           (window-parameters . ((no-delete-other-windows . t)))))))

(defun my-indirect-buffer ()
  (interactive)
  (let ((current-prefix-arg 4))                       ;; emulate C-u
    (call-interactively 'org-tree-to-indirect-buffer)))

(defun scriv()
  (interactive)
  (when (require 'wc-mode nil t)
    (wc-mode))
  (toggle-frame-maximized)
  (my-sidebars)
  (global-set-key (kbd "M-s i") 'my-indirect-buffer))