diff options
Diffstat (limited to 'emacs/site-lisp/single-header.el')
| -rwxr-xr-x | emacs/site-lisp/single-header.el | 171 |
1 files changed, 129 insertions, 42 deletions
diff --git a/emacs/site-lisp/single-header.el b/emacs/site-lisp/single-header.el index 06faff5..2713c5b 100755 --- a/emacs/site-lisp/single-header.el +++ b/emacs/site-lisp/single-header.el @@ -1,40 +1,103 @@ -(provide 'single-header) +(require 'ednc) +(require 'battery) +(require 's) +(require 'dash) -(defvar single-header--current-header-buffer nil "Read the name") +;; not toggled with the mode to prevent user from having to restart +;; applications producing notifs. +(when (equal window-system 'x) + (ednc-mode 1)) -(defvar single-header-format '(make-header-info-string) "evaluated to fill the header") +;; testing +;; (require 'notifications) +;; (notifications-notify :title "2st test" :body "hello, world" :app-name "EDNC" +;; :actions '("default" "default")) + +(defvar single-header-update-increment 3 "Number of seconds before updating the header again.") + +(defvar single-header--current-header-buffer nil "Read the name") (defface single-header '((default . (:background "#000000" :family "Source Code Pro"))) "Face for top line") -(require 'battery) -(defun with-face (str &rest face-plist) +(setq single-header--active-notifs nil) +(setq single-header--timer nil +;; "Timer that triggers updates of the header contents. Use `single-header-update' for forcing updates." + ) + +(defun single-header--with-face (str &rest face-plist) + "Convenience wrapper for `add-face-text-property'." (add-face-text-property 0 (length str) face-plist t str) str) -(defun make-header-info-string () - "generates the mode line string that contains all the info to the right" +(defun single-header--register-notif-change (old new) + "Function to hook `ednc-notification-presentation-functions'." + (when new + (push new single-header--active-notifs)) + (when (and old + (member old single-header--active-notifs)) + (setq single-header--active-notifs + (remove old single-header--active-notifs)))) + +(defun single-header--make-notif-string () + "Produce a string representation of the active notifications." + (mapconcat (lambda (e) + (format "[%s | %s | %s] " + (s-truncate 8 (ednc-notification-app-name e)) + (s-truncate 8 (ednc-notification-summary e)) + (s-truncate 20 (ednc-notification-body e))) + ) + (ednc-notifications))) + +(defun single-header-dismiss (num) + "Dismiss the most recent notification from the header line. With a prefix +arg, dismiss all the notifications." + (interactive "p") + (cond ((and (natnump num) (>= num 4)) + (mapc 'ednc-dismiss-notification (ednc-notifications))) + (t + (let ((notifs (ednc-notifications))) + (when notifs + (ednc-dismiss-notification (car notifs)))))) + (single-header-update)) + +(defun single-header-format () + "Evaluated in the header buffer when empty to fill the buffer." + (let* ((win (get-buffer-window (current-buffer))) + (win-width (window-max-chars-per-line win 'single-header)) + (info (single-header--make-header-info-string)) + (info-width (string-width info)) + (notifs (s-truncate (- win-width info-width 2) + (single-header--make-notif-string))) + (notifs-width (string-width notifs)) + (filled (min win-width (+ info-width notifs-width))) + (padding-width (- win-width filled)) + (padding (make-string padding-width ? ))) + (setq notifs (single-header--with-face notifs 'single-header)) + (setq padding (single-header--with-face padding 'single-header)) + (setq info (single-header--with-face info 'single-header)) + (insert notifs padding info))) + + + +(defun single-header--make-header-info-string () + "Generates the mode line string that contains all the info to the right." (let ((str (concat - (with-face (battery-format "[%b%p%%] " (and battery-status-function (funcall battery-status-function))) + (single-header--with-face (battery-format "[%b%p%%] " (and battery-status-function (funcall battery-status-function))) :weight 'bold) - (with-face (let* ((mi (memory-info)) + (single-header--with-face (let* ((mi (memory-info)) (tm (float (car mi))) (fm (float (cadr mi))) (ts (float (caddr mi))) (fs (float (cadddr mi)))) (format "{%.2f %.2f} " (- 1 (/ fm tm)) (- 1 (/ fs ts)))) :foreground "#00ced1") - (with-face (format "<%03.2f> " (car (load-average 1))) + (single-header--with-face (format "<%03.2f> " (car (load-average 1))) :foreground "#da70d6") (format-time-string "%a, %b %+4Y-%0m-%0d ") - (with-face (format-time-string "%R") + (single-header--with-face (format-time-string "%R") :weight 'bold) ))) - (setq str (concat (make-string - (- (window-max-chars-per-line (minibuffer-window) 'single-header) - (length str)) - ? ) - str)) - (with-face str 'single-header))) + (single-header--with-face str 'single-header))) (defun single-header-init-buffer (buf) (with-current-buffer buf @@ -69,7 +132,7 @@ (window-preserve-size win nil t)))) (defun single-header-show (buf) - "show / make a header" + "Show the header, making it if necessary." (if (buffer-live-p buf) (let ((win (display-buffer-in-side-window buf '((side . top) (slot . -100))))) @@ -77,43 +140,67 @@ (single-header-make))) (defun single-header-make () - "create the fake header line" + "Create the header and show it." (interactive) + + (let ((registered + (or (equal 'single-header--register-notif-change + ednc-notification-presentation-functions ) + (and (listp ednc-notification-presentation-functions) + (-contains? ednc-notification-presentation-functions + 'single-header--register-notif-change))))) + (unless registered + (if (listp ednc-notification-presentation-functions) + (push 'single-header--register-notif-change ednc-notification-presentation-functions) + (list 'single-header--register-notif-change ednc-notification-presentation-functions)))) (unless (buffer-live-p single-header--current-header-buffer) (let ((buf (generate-new-buffer "*header*"))) (single-header-init-buffer buf) (setq single-header--current-header-buffer buf) - (single-header-show buf)))) + (single-header-show buf))) + (unless (timerp single-header--timer) + (setq single-header--timer (run-with-timer 0 single-header-update-increment 'single-header-update)))) (defun single-header-delete () - "remove an existing header buffer" + "Remove an existing header buffer." (interactive) + (let ((reg-list (and (listp ednc-notification-presentation-functions) + (-contains? ednc-notification-presentation-functions + 'single-header--register-notif-change))) + (reg-equal (or (equal 'single-header--register-notif-change + ednc-notification-presentation-functions ) + ))) + (when reg-list + (delete 'single-header--register-notif-change + ednc-notification-presentation-functions)) + (when reg-equal + (setq ednc-notification-presentation-functions + 'ednc--update-log-buffer))) + + (when (timerp single-header--timer) + (cancel-timer single-header--timer) + (setq single-header--timer nil)) (when (buffer-live-p single-header--current-header-buffer) (kill-buffer single-header--current-header-buffer))) (defun single-header-update () - "update the contents of the header line according to `single-header-format'" + "Update the contents of the header line by calling `single-header-format' +with the header buffer current and empty." (when (buffer-live-p single-header--current-header-buffer) (with-current-buffer single-header--current-header-buffer (erase-buffer) - (insert (eval single-header-format))) - - ;; (when exwm-state - ;; (exwm-input--set-active-window - ;; (or (frame-parameter exwm-workspace--current 'exwm-outer-id) - ;; xcb:Window:None))) - )) - -(add-hook 'after-make-frame-functions (lambda (frame) - (with-selected-frame frame - (single-header-show single-header--current-header-buffer)))) - -;; (use-package lv - ;; :custom ((lv-use-separator . nil))) - -;; do init frame seperately -(single-header-show single-header--current-header-buffer) -(setq single-header--timer nil) -(unless single-header--timer - (setq single-header--timer (run-with-timer 0 3 'single-header-update))) + (single-header-format)))) + +(define-minor-mode single-header-mode + "Global minor mode to enable a single info line at the top of each frame." + :global t + :init-value nil + ;; :keymap '(("s-l d" . 'single-header-dismiss) + ;; ("s-l t" . 'single-header-mode)) + :interactive t + (if (not single-header-mode) + (single-header-delete) + (single-header-make))) + +(provide 'single-header) |
