;;; dashboard.el --- My daashboard -*- lexical-binding: t; -*- (defun dashboard-center-string (str) "Return a centered string." (let ((current-window-width (1- (window-width nil t))) (str-width (string-pixel-width str))) (cond ((display-graphic-p) (concat (propertize (string 32) 'display (list 'space :width (list (floor (- current-window-width str-width) 2)))) str)) (t (concat (make-string (round (- current-window-width str-width) (* 2 (string-pixel-width (string 32)))) 32) str))))) ;;;###autoload (defvar dashboard-buffer-name "durand" "The name of the buffer for the dashboard.") ;; TODO: Change this ASCII art. ;;;###autoload (defvar dashboard-cat-text (list " IIIII " " IIIIIII " "I=======|| IIIII " "I =============I=====I=====I====== " "I IIIIIII - I I I I " "I IIIII -I-========I=====I I " "I -- I I I I " "I \\\\\\I I I I " "I == I I I " "I / \\I I I " "I / III I I " "I \\\\==I I I " "I \\ I I I " "I ===I I I " "I / \\I I I " "I / III I I " "I \\\\==I I I " "I III I I I " "I III II I I " "I I IIII I I " "I IIIIIII I I " "I ===I I I " "I // I I I " "I =====I I I " "I // I I I " "\\\\ \\\\ \\\\ \\\\ \\\\" ;; " " ;; " /\\ " ;; " / \\ " ;; " / =\\= " ;; " / - \\=----- " ;; " / |.| / " ;; " \\\\ - - / " ;; " \\\\ |.| | " ;; " / \\\\ - / " ;; " / \\\\ / " ;; " ||==========| ========\\=| " ;; " ||==========| -- | " ;; " | || /==== | " ;; " == | / \\ \\ " ;; " | | \\ \\ " ;; " ==== ==== " ) "A clumsy text representation of a cute cat.") ;;;###autoload (defun dashboard (&optional force) "Create the dashboard buffer. If FORCE is non-nil, re-gerenate the dashboard buffer." (interactive) (let ((dashboard-exists-p (get-buffer dashboard-buffer-name)) (dashboard (get-buffer-create dashboard-buffer-name)) (inhibit-read-only t)) (cond ((and (not force) dashboard-exists-p) (switch-to-buffer dashboard)) (t (with-current-buffer dashboard (erase-buffer) (cond (nil;; (display-graphic-p) (let ((image (create-image (expand-file-name "बोधिचित्तं.png" user-emacs-directory) nil nil :scale 0.5))) (insert (make-string 3 10) (dashboard-center-string (propertize " " 'display image 'rear-nonsticky '(display)))))) ((let ((width (with-temp-buffer (insert (mapconcat #'identity dashboard-cat-text (string 10))) (car (buffer-text-pixel-size)))) (space-width (string-pixel-width (string 32)))) (mapc (lambda (text) (insert (make-string (floor (- (window-width nil t) space-width width) (* 2 space-width)) 32) text 10)) dashboard-cat-text)))) (newline 5) (insert (dashboard-center-string (propertize "ॐ मणिपद्मे हूम्" 'face (list :height 600)))) (goto-char (point-min)) (set-buffer-modified-p nil) (read-only-mode 1) (set 'mode-line-format '("%e" (:eval (modeline-format-dashboard)))) (set 'default-directory user-emacs-directory) (view-mode 1) (dashboard-mode)))) dashboard)) (set 'initial-buffer-choice #'dashboard) ;;; Dedicated major mode (define-derived-mode dashboard-mode nil "Dashboard" "Major mode for the dashboard buffer. The main purpose is to provide a dedicated keymap to access common functionalities more conveniently." (font-lock-mode -1) (setq buffer-undo-list t) (setq-local cursor-type nil) (setq-local mode-line-format (list "%e" (list :eval (list 'modeline-format-dashboard))))) (let ((m dashboard-mode-map)) (define-key m (vector ?l) #'blist) (define-key m (vector ?L) #'rlist-list-registers) (define-key m (vector ?b) #'bookmark-jump) (define-key m (vector ?B) #'durand-jump-bookmark-new-tab) (define-key m (vector ?T) #'modeline-toggle) (define-key m (vector ?t) #'durand-view-timers-or-temps) (define-key m (vector ?o) #'durand-open-object) (define-key m (vector ?g) #'gnus) (define-key m (vector ?h) #'durand-ibuffer) (define-key m (vector ?f) #'find-file) (define-key m (vector ?F) #'find-file-other-tab) (define-key m (vector ?a) #'dashboard-org-agenda) (define-key m (vector ?c) #'dashboard-clear) (define-key m (vector ?C) #'dashboard-org-capture) (define-key m (vector ?p) #'project-switch-project) (define-key m (vector ?x) #'execute-extended-command) (define-key m (vector ?n) #'novel)) ;;; Define novel command as a wrapper, if not already loaded (cond ((functionp 'novel)) (t (defun novel () "Load novel package." (load "/Users/durand/elisp_packages/novel/novel.el" nil nil t)))) ;;; load Org if not loaded already (defmacro dashboard-preload (symbol file-to-load) "Define a dispatch function for the symbol." (list 'defun (intern (format "dashboard-%s" (symbol-name symbol))) (list (intern "&rest") 'args) (format "A dispatch function for `%s'. This function loads \"%s\" if `%s' is not already loaded, and calls `%s' otherwise." (symbol-name symbol) file-to-load (symbol-name symbol) (symbol-name symbol)) (list 'interactive (list #'list 'current-prefix-arg t)) (list 'cond (list (list 'not (list #'functionp `(quote ,symbol))) (list #'load-config file-to-load)) (list (list #'funcall `(quote ,symbol) 'args))))) (dashboard-preload org-agenda "org-conf.el") (dashboard-preload org-capture "org-conf.el") (dashboard-preload org-store-link "org-conf.el") ;;; ibuffer clear (defun dashboard-clear () "Run `durand-ibuffer-clear' while in the dashboard." (interactive) (let ((inhibit-message t)) (ibuffer) (durand-ibuffer-clear))) ;;; Modify killing buffers ;;;###autoload (defun dont-kill-dashboard-fn () "Don't kill the dashboard buffer." ;; The function message returns the message, so applying not will ;; produce nil as needed. ;; "Please don't kill the dashboard buffer" (not (cond ((eq (current-buffer) (get-buffer dashboard-buffer-name)) (message "न निहन्याद्घाटीफलकनिधानकम्"))))) (add-hook 'kill-buffer-query-functions 'dont-kill-dashboard-fn) (provide 'dashboard) ;;; dashboard.el ends here.