145 lines
5.1 KiB
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; org-clock-waybar.el --- Summary
;; Copyright (C) 2021 Gergely Polonkai
;; Author: Gergely Polonkai <>
;; Keywords: org, clocking, waybar
;; Version: 1.0
;; Package-Requires: ((emacs "26.1"))
;; URL:
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <>.
;;; Commentary:
;; Export the currently clocked-in task in JSON format that Waybar can process
;; To use it, customize the `org-clock-waybar-filename' variable (defaults to
;; $XDG_CONFIG_HOME/waybar-current-task.json) and add the following snippet to
;; your Waybar config:
;; "custom/org": {
;; "format": " {}",
;; "return-type": "json",
;; "restart-interval": 5,
;; "exec": "cat /home/yourusername/.cache/waybar-current-task.json"
;; }
;;; Code:
(require 'xdg nil t)
(require 'json)
(require 'org-clock)
(defgroup org-clock-waybar nil
"Send current clocked task to a JSON file for Waybar visualization"
:group 'emacs)
(defcustom org-clock-waybar-filename
(if (fboundp 'xdg-cache-home)
(expand-file-name "waybar-current-task.json" (xdg-cache-home))
(expand-file-name "~/.cache/waybar-current-task.json"))
"Name of the file to save task data to."
:type 'string
:group 'org-clock-waybar)
(defcustom org-clock-waybar-not-clocked-in-text
"Not clocked in"
"Text to display when not clocked in on any task."
:type 'string
:group 'org-clock-waybar)
(defconst org-clock-waybar-filename-coding-system
(if (coding-system-p 'utf-8-emacs)
"Coding system of the file `org-clock-waybar-filename'.")
(defsubst org-clock-waybar--get-task-title ()
"Get the title of TASK."
(when (org-clocking-p) (substring-no-properties org-clock-current-task)))
(defsubst org-clock-waybar--get-task-category ()
"Get the category of TASK."
(when (org-clocking-p) (get-text-property 0 'org-category org-clock-current-task)))
(defun org-clock-waybar--get-tooltip ()
"The default tooltip to send to waybar."
(when (org-clocking-p)
(let ((clocked-time (org-clock-get-clocked-time)))
(format "%s: %s (%s)"
(org-duration-from-minutes clocked-time)))))
(defun org-clock-waybar--get-tags ()
"Get the tags of the currently clocked-in task."
(when (org-clocking-p)
(or (org-with-point-at org-clock-marker (org-get-tags))
(defun org-clock-waybar--get-clocked-task-json ()
"Get the currently clocked-in tasks data as a stringified JSON object.
The output is in JSON format constructed in a way so Waybar can process it.
If there is no clocked in task, alt becomes empty and text will be set to the
value of `org-clock-waybar-not-clocked-in-text'."
(let* ((category (org-clock-waybar--get-task-category))
(title (org-clock-waybar--get-task-title))
(tooltip (org-clock-waybar--get-tooltip))
(output (json-new-object)))
(setq output (json-add-to-object
(or title org-clock-waybar-not-clocked-in-text)))
(setq output (json-add-to-object output "alt" (or category "")))
(setq output (json-add-to-object output "tooltip" (or tooltip "")))
(setq output (json-add-to-object output "class" (or (org-clock-waybar--get-tags) "")))
(setq output (json-add-to-object output "percentage" ""))
(json-encode output)))
(defun org-clock-waybar-save-task ()
"Save the current clocked in task to `org-clock-waybar-filename'."
(set-buffer-file-coding-system org-clock-waybar-filename-coding-system)
(insert (org-clock-waybar--get-clocked-task-json))
(write-file org-clock-waybar-filename)))
(defun org-clock-waybar-ouptut-task ()
"Output the current task in JSON format Waybar can understand.
This function is ought to be used via Emacsclient:
emacsclient --eval '(org-clock-waybar-output-task)'"
(let* ((output (org-clock-waybar--get-clocked-task-json))
(start 0)
(end (length output)))
(set-text-properties start end nil output)
(defun org-clock-waybar-setup ()
"Setup org-clock-waybar.
It adds `org-clock-waybar-save-task' to both `org-clock-in-hook' and
(add-hook 'org-clock-cancel-hook #'org-clock-waybar-save-task)
(add-hook 'org-clock-in-hook #'org-clock-waybar-save-task)
(add-hook 'org-clock-out-hook #'org-clock-waybar-save-task)
(add-hook 'kill-emacs-hook #'org-clock-waybar-save-task))
(provide 'org-clock-waybar)
;;; org-clock-waybar.el ends here