2018-09-17: Record Org-mode Recent Activity

So I checked the notion tool recently. It's pretty good if everyone around use it. But as an emacs user, I still prefer org-mode.

It's just there's one functionality I never thought about when I was using org-mode, the ability to record your activity. Like when you reschedule somthing or change the state of tasks.

I did some search online and came up with a solution. I'm pretty sure there's better ways to do so. I'll just put the codes here. It leverages the org-agenda-custom-commands and the :LOGBOOK: feature. And the code is mainly from here with some modification.

    ;; enable the log feature
(setq org-log-into-drawer t)
(setq org-log-reschedule 'time)
(setq org-log-redeadline 'note)
(setq org-log-note-clock-out t)

;; add T: before timestamp for easy regex search
(setq org-log-note-headings '((done . "CLOSING NOTE T:%t")
                              (state . "State %-12s from %-12S T:%t")
                              (note . "Note taken on T:%t")
                              (reschedule . "Rescheduled from %S on T:%t")
                              (delschedule . "Not scheduled, was %S on T:%t")
                              (redeadline . "New deadline from %S on T:%t")
                              (deldeadline . "Removed deadline, was %S on T:%t")
                              (refile . "Refiled on T:%t")
                              (clock-out . "Clocked out on T:%t")))

(defun +org/find-state (&optional end)
  "Used to search through the logbook of subtrees.

    Looking for T:[2018-09-14 Fri 10:50] kind of time stamp in logbook."
  (let* ((closed (re-search-forward "^CLOSED: \\[" end t))
         (created (if (not closed) (re-search-forward "^:CREATED: \\[" end t)))
         (logbook (if (not closed) (re-search-forward ".*T:\\[" end t)))
         (result (or closed logbook created)))

(defun +org/date-diff (start end &optional compare)
  "Calculate difference between  selected timestamp to current date.

  The difference between the dates is calculated in days.
  START and END define the region within which the timestamp is found.
  Optional argument COMPARE allows for comparison to a specific date rather than to current date."
  (let* ((start-date (if compare compare (calendar-current-date))))
    (- (calendar-absolute-from-gregorian start-date) (org-time-string-to-absolute (buffer-substring-no-properties start end)))))

(defun +org/last-update-before (since)
  "List Agenda items that updated before SINCE day."
  (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))))
    (let* ((subtree-end (save-excursion (org-end-of-subtree t)))
           (subtree-valid (save-excursion
                            (forward-line 1)
                            (if (and (< (point) subtree-end)
                                     ;; Find the timestamp to test
                                     (+org/find-state subtree-end))
                                (let ((startpoint (point)))
                                  (forward-word 3)
                                  ;; Convert timestamp into days difference from today
                                  (+org/date-diff startpoint (point)))
      (if (and subtree-valid (>= subtree-valid since))

(defun +org/has-child-and-last-update-before (day)
  (if (+org/has-child-p) (point)
    (+org/last-update-before day)))    

So now we can use the +org/last-update-before or +org/has-child-and-last-update-before function in org-agenda-custom-commands to filter activities updated since SINCE days ago. Like this.

    (setq org-agenda-custom-commands
      '(("R" "Recent activity"
         ((tags "*"
                ((org-agenda-overriding-header "Recent Activity")
                 (org-agenda-skip-function '(+org/has-child-and-last-update-before 7)))))
         nil nil)))    

The code will only search for timestamps in ":LOGBOOK:" prefexd with T: or :CREATED: or :CLOSED timestamps. It works fine and helps me sometimes. Maybe I should write a agenda sort function to let them ordered by changed time. Fine for me right now.

2018-08-11: after tring persp-mode

After last post about tring emacs workspace management, I tried persp-mode. It comes out that it's not that simple to implement a workspace auto-switch feature. It's not just find-file-hook and advice for switch-buffer. There are too many commands need to advice and hook (select-window, kill-buffer-hook ...). Cause there's no "buffer-focus-in-hook". And it's not easy to build one with persp-mode.

There is one package in melpa that implement per buffer buffer-focus-in-hook and buffer-focus-out-hook by hacking on buffer-list-update-hook. But persp-mode also manipulate the buffer-list. It won't work out.

Then I realize that I just want to have workspace on buffer management, like the ibuffer option above. I can easily get that feature. I just rebind my buffer-switch key to counsel-projectile-switch-to-buffer and everything works great.

It turns out that compared with projectile, persp only offers workspace specific window configuration. So I don't need it if I only want buffer level workspace. And it also add unexpacted behavior when I test my auto-switch implementation (buffer and window configuration switched at the same time), which makes me wonder that workspace auto-switch is a bad idea.

Although it looks like that I waste bunch of time to find a single rebind. I do find lots useful stuff on these workspace, layout, window management packages and implementations. I might write another post for about that.

2018-08-07: emacs workspace management

Recently I'm asked to help on a project. The problem is there're a lot files with same name in different directories and same name with my other project. I'm using ivy-switch-buffer to switch between opened buffer. And it needs more keystrokes in this project to switch to the desired buffer. So I'm looking for some workspace management aproch in emacs to make my finger not that tired after work.

After googling for a little while, I find there are so many ways to manage workspace in emacs.

The cons of the first two is that you need to deliberately switch workspace when you are going to open files in other workspace. The pros is that they provide perfect isolation, no need to tweak buffer switch functions.

For persp-mode, the pros is that with custom code, maybe it's not hard to implement the workspace auto-switching function. It has eye candy in mode line or title bar if you want them. The cons is that you need to implement the auto-switching function or remember to switch workspace manually.

For purpose-mode, you may need multiple high resolution screen.

For ibuffer, it's not typically "workspace". It depends on how many buffers you have and how familiar you are with the ibuffer filter functionality.

For tabbar, eye candy and custom function is needed.

So it really depends on

I may try persp-mode first. Wish me luck.

2018-02-12: My Karabiner Elements configuration

UPDATE 2018-09-19 Wed

My config in KE-complex-modifications is outdated. I'm now using GokuRakuJoudo to config karabiner. It enables user to write the configuration in a much more compact karabiner.edn file, you can check out mine. I'll write a post about it soon. If your karabiner.json is bloated, you may want to try it. Recommend to check the tutorial first.


This post are descriptions and tutorial of my personal KE complex modification.

I merged my personal Karabiner Elements configuration into the official repo several days ago. You can import my personal rules here. To achieve efficiency, I use karabiner with Alfred mainly through alfred workflow external trigger and osascript (command line tool for calling AppleScript code). Here are these configurations. Please note that I update my configurations every day. So I can't keep this post up to date. The key here is to introduce a system for launching apps, invoking scripts and all stuffs that can be done with shell (everything). When you can get anything you want with few key strokes, it feels great.

Download all my workflow from dropbox , please contact me when this link broken. I may update this post for each specific config if I have time in the future (may not happen). If you have any problems or ideas, please open an issue in my dotfile repo. And you can also check KE-complex_modifications official repo for more rules and discussion.

Update: The old download link is broken and I don't have time to maintain all these workflows up to date. Now that the core thing here is to use alfred workflow's external trigger feature, I create a app launcher workflow as a sample.

2017-11-25: org-agenda bitbar plugin

UPDATE: The agenda plugin has been merged into the official plugin repo. You can now find the plugin here.

Bitbar is a macos application that can add custom menu bar buttons. I'm recently learning managing projects with org-mode. And we all know that org-agenda is great.

So I write a bitbar plugin, agenda to display some of my agenda in menu bar.

Read the whole article ...

2017-11-09: Use zsh in emacs

I used to use vim with tmux in a terminal emulator. After changing to emacs. It didn't take much time for me to realize that emacs in GUI works better.

The problem is I still want the old behavior. I tried about three times using my zsh shell in emacs. I'm not here telling those failed attempts. I want to write it down because of a recent discovery.

When I restructure my zsh configurations, I find the z-shell works fine with with zero config. That's when I finally discover that it's the plugins and configurations that make zsh and emacs incompatible. What's more, I find these lines. They must come from some emacs package's readme instruction. The original one is telling zsh don't do something when it's in emacs.

    if [ -n "$INSIDE_EMACS" ]; then

So I thought, I can just use these line with my zsh configuration(prezto). It works fine now after some little test. It turns out the default zsh-autocompletion is not playing well with emacs. I use the if...else code telling zsh don't load autosugestion while in emacs. And everything is fine now.

That's it. Maybe I'll dig in for getting autocompletion back in emacs someday.

2017-10-28: Halt and Catch Fire

Just finish the Halt and Catch Fire, really great show. It makes me think about that everyone is full of story in their life, amazing to others but definitely not to themselves, like Joe in the series.

It's just that I think Joe is "right" in some way. The right is some kind of his every decision of fresh start, it's so decisive. It makes the character fear nothing. He desires success so much but go through his failer and go for the fresh start so quick. But on the other hand, he is so emotional, about his failer, about Gordon's die.

These characters normally can't be on the same person. Maybe that's why it makes me think Joe is "right".

2017-10-21: About

Blog about coding and every other things in daily life.

2016-10-09: Git 指南


Read the whole article ...