# Leverage recorded macros to learn elisp and hack together workflows in Emacs

The primary power of Emacs is that you can create customised workflows to suit your needs. However, lisp is probably not a language that many learn as a typical requirement in the academic systems, perhaps even for a software engineer.

How would one then start customisting Emacs? One way would be to hunt for snippets from forums like reddit and stack overflow, and customise them.

Another easy way to learn a programming language, especially one that is intrinsic to a software is to record macros and edit these macros. Emacs is no different in this regard, and in fact makes it easy being a self-documenting text editor.

The elmacro package reduces some of the burden. The recorded macro does require a subsequent clean-up to be useful, which is still easier than coding lisp from scratch. In any case, exploring the recorded code will eventuall lead towards proficiency in writing lisp.

This blog post provides a more detailed introduction, including creating a menu entry for elmacro. As highlighted by the blog, some commands do not register in Emacs, since external packages handle those functions.

For example, I have 3 main repositories where I commit my work. This is a frequent, repetitive process that is often done till (and at) the last minute.

These are snippets that were developed leveraging elmacro:

;; Maximise current frame, open scimax user directory,

;; call magit, switch window and open the scimax directory

;; Scimax magit status and dired

(defun sr/windows-magit-scimax ()
(interactive)
(ace-delete-other-windows)
(dired "~/scimax/user/")
(switch-window-then-split-right nil)
(magit-status "~/scimax/")
(switch-window)
(split-window-vertically)
(dired-up-directory)
(windmove-right)
)

;; Maximise current frame, open org directory, call magit

;; my_org magit status

(defun sr/windows-magit-org ()
(interactive)
(ace-delete-other-windows)
(magit-status "~/my_org/")
)

;; Maximise current frame, call magit for my_projects directory

;; split buffer and call dired in case I need to navigate to a particular directory.

;; the latter can also be done via magit itself if desired.

(defun sr/windows-magit-projects ()
(interactive)
(ace-delete-other-windows)
(switch-window-then-split-right nil)
(magit-status "~/my_projects/")
(switch-window)
(dired "~/my_projects/")
(switch-window)
)



Another more complicated example, is using projectile to switch to a project, call a particular file in the project and then split the buffer and open the tasks of that particular project with a narrowed view.

I capture each project’s tasks and notes separately in an org file using org-projectile. This is useful especially for coding projects so that the code is better separated from notes and yet linked.

;; This is to rapidly switch between projects and have a similar window configuration,

;; i.e. a main file, and a narrowed view of the tasks heading.

(defun sr/windows-projects ()
(interactive)
(ace-delete-other-windows)
(switch-window-then-split-right nil)
(projectile-switch-project)
(switch-window)
(widen)
(helm-org-rifle-current-buffer)
(org-narrow-to-subtree)
(outline-show-children)
)



These are not perfect. For example, I’d rather have to select the project name only once and have that feed into helm-org-rifle. These are topics of future exploration.

What then remained was being able call these functions with a few keypresses. Hydras enable this.


(defhydra sr/process-window-keys ()
"
Key^^   ^Workflow^
--------------------
o       org magit
s       scimax magit
p       projects magit
w       select project and set window config
SPC     exit
"
("o" sr/windows-magit-org )
("p" sr/windows-magit-projects )
("s" sr/windows-magit-scimax )
("w" sr/windows-projects)
("SPC" nil)
)

(global-set-key (kbd "<f8> m") 'sr/process-window-keys/body)



With the above in place, now all I have to do is call the menu to choose the desired function by typing F8 m and then type o or p and so on. The hydra exits with Space, which makes it easy to switch to another project in case there is nothing to commit in the current choice.

Though simple and in many ways primitive - these functions have still saved me a lot of repetitive acrobatics on my keyboard and I enjoy using Them.