#+TITLE: Emacs Configuration #+AUTHOR: Benson Chu #+PROPERTY: header-args :tangle "~/.emacs.d/config-base.el" :comments both * Enable lexical binding #+begin_src emacs-lisp :comments no ;;; -*- lexical-binding: t -*- #+end_src * Bugs ** Need this to fix broken config #+begin_src emacs-lisp (use-package magit-popup) #+end_src * custom-tangle #+begin_src emacs-lisp (defun tangle-elisp () (interactive) (org-babel-tangle nil nil 'emacs-lisp)) #+end_src * Neo keyboard issues #+BEGIN_SRC emacs-lisp (global-set-key (kbd "M-Ä") 'eval-expression) (defun reset-keyboard () (interactive) (shell-command "setxkbmap de neo_dvorak")) #+END_SRC * Emacs ** Reload Config #+BEGIN_SRC emacs-lisp (defun reload-config () (interactive) (load-file "~/.emacs.d/init.el")) #+END_SRC ** which-key #+BEGIN_SRC emacs-lisp (use-package which-key) (setq which-key-idle-delay 3) (which-key-mode) #+END_SRC ** advice for shell-command #+begin_src emacs-lisp (defun my/shell-command-advice (&rest args) (switch-to-buffer "*Shell Command Output*")) ;;(advice-add #'shell-command :after #'my/shell-command-advice) #+end_src ** uniq emacs #+begin_src emacs-lisp (defun case-fold-string= (a b) (eq t (compare-strings a nil nil b nil nil t))) (defun case-fold-string-hash (a) (sxhash (upcase a))) (define-hash-table-test 'case-fold 'case-fold-string= 'case-fold-string-hash) (defun uniq (beg end) "Print counts of strings in region." (interactive "r") (let ((h (make-hash-table :test 'case-fold)) (lst (split-string (buffer-substring-no-properties beg end) "\n" 'omit-nulls " ")) (output-func (if current-prefix-arg 'insert 'princ))) (dolist (str lst) (puthash str (1+ (gethash str h 0)) h)) (maphash (lambda (key val) (apply output-func (list (format "%d: %s\n" val key)))) h))) #+end_src * Look and feel ** Ocodo #+BEGIN_SRC emacs-lisp# (use-package ocodo-svg-modelines) #+END_SRC ** Font #+BEGIN_SRC emacs-lisp ;;(set-face-attribute 'default t :font "Dotsies Training Wheels-20") ;;(add-to-list 'default-frame-alist '(font . "Dotsies Training Wheels-20")) ;; (set-default-font "LinuxLibertine") ;; (set-default-font "Hack 10") ;; (set-default-font "UbuntuMono 11") ;; (set-default-font "OfficeCodePro 11") ;; "Tamzen" ;; "SourceCodePro" ;; "Gohu Gohufont" (set-default-font "RobotoMono-10") (add-to-list 'default-frame-alist '(font . "RobotoMono-10")) (set-face-attribute 'default nil :family "RobotoMono" :weight 'normal) (set-fontset-font t nil (font-spec :size 10 :name "RobotoMono")) (set-fontset-font t 'unicode (font-spec :size 10 :name "FontAwesome")) (set-fontset-font t 'unicode (font-spec :size 16 :name "DejaVu Sans Mono")) ;; (set-frame-font "Menlo") (defun reading-buffer () (interactive) (setq buffer-face-mode-face '(:family "LinuxLibertine" :height 200)) (buffer-face-mode)) #+END_SRC * Navigation ** Helm & counsel/ivy #+BEGIN_SRC emacs-lisp (use-package helm) (require 'helm-config) ;; (helm-mode 1) ;; (setq ivy-initial-inputs-alist nil) (use-package smex) (use-package counsel) ;; (advice-add 'ivy-completion-in-region :before (lambda (start end collection &optional predicate) (insert " "))) ;; (global-set-key (kbd "C-x b") 'counsel-switch-buffer) #+END_SRC *** f3 helm #+begin_src emacs-lisp (use-package f3) #+end_src ** Swiper or counsel-grep #+BEGIN_SRC emacs-lisp (global-set-key (kbd "C-S-s") 'counsel-grep-or-swiper) ;;(global-set-key (kbd "C-s") 'isearch-forward) (setq counsel-grep-base-command "grep --ignore-case -E -n -e %s %s") #+END_SRC ** help should still use regular search #+begin_src emacs-lisp (define-key Info-mode-map (kbd "C-s") 'isearch-forward) #+end_src ** Evil mode #+BEGIN_SRC emacs-lisp (use-package evil) (global-set-key (kbd "C-z") 'evil-local-mode) (setq evil-insert-state-modes nil) (setq evil-motion-state-modes nil) (setq evil-default-state 'emacs) (evil-set-initial-state 'term-mode 'emacs) (evil-set-initial-state 'help-mode 'emacs) (evil-mode 1) #+END_SRC * Tools ** Encryption #+BEGIN_SRC emacs-lisp (require 'epa-file) (epa-file-enable) (setq epa-pinentry-mode 'loopback) (setq epa-file-cache-passphrase-for-symmetric-encryption t) (setenv "GPG_AGENT_INFO" nil) (setq epg-gpg-program "gpg2") (setq auth-source-debug t) (setq auth-sources '((:source "~/.emacs.d/secrets/.authinfo.gpg"))) ;; (defun always-use-loopback (fun context args) ;; (setf (epg-context-pinentry-mode context) epa-pinentry-mode) ;; (funcall fun context args)) ;; (advice-remove 'epg--start :around #'always-use-loopback) #+END_SRC ** dired *** dired-hacks #+begin_src emacs-lisp (use-package dired-filter) (use-package dired-narrow) (define-key dired-filter-map (kbd "F") 'dired-narrow-fuzzy) (setq dired-filter-group-saved-groups '(("default" ("PDF" (extension . "pdf")) ("LaTeX" (extension "tex" "bib")) ("Org" (extension . "org")) ("Archives" (extension "zip" "rar" "gz" "bz2" "tar"))))) (use-package dired-collapse) #+end_src *** dired-du #+begin_src emacs-lisp (use-package dired-du) #+end_src *** youtube-dl #+begin_src emacs-lisp (require 'dired-aux) (defvar dired-filelist-cmd '(("vlc" "-L"))) (defun dired-start-process (cmd &optional file-list) (interactive (let ((files (dired-get-marked-files t current-prefix-arg))) (list (dired-read-shell-command "& on %s: " current-prefix-arg files) files))) (let (list-switch) (start-process cmd nil shell-file-name shell-command-switch (format "nohup 1>/dev/null 2>/dev/null %s \"%s\"" (if (and (> (length file-list) 1) (setq list-switch (cadr (assoc cmd dired-filelist-cmd)))) (format "%s %s" cmd list-switch) cmd) (mapconcat #'expand-file-name file-list "\" \""))))) (define-key dired-mode-map "r" 'dired-start-process) (defun watch-youtube () (interactive) (dired "~/big_files/Videos/youtube-dl") (local-set-key (kbd "RET") 'dired-start-process)) #+end_src *** async-command #+begin_src emacs-lisp ;; (defun my/async-shell-command (command &optional output-buffer error-buffer) ;; (interactive ;; (list ;; (read-shell-command "Async shell command: " nil nil ;; (let ((filename ;; (cond ;; (buffer-file-name) ;; ((eq major-mode 'dired-mode) ;; (dired-get-filename nil t))))) ;; (and filename (file-relative-name filename)))) ;; current-prefix-arg ;; shell-command-default-error-buffer)) ;; (unless (string-match "&[ \t]*\\'" command) ;; (setq command (concat command " &"))) ;; (shell-command command output-buffer error-buffer)) ;; (add-to-list 'display-buffer-alist ;; (cons "\\*Async Shell Command\\*.*" (cons #'display-buffer nil))) ;; (setq display-buffer-alist (remove-if (lambda (a) (string= (car a) "\\*Async Shell Command\\*.*")) display-buffer-alist) #+end_src *** rename-follow #+begin_src emacs-lisp (defun my/dired-do-create-files (op-symbol file-creator operation arg &optional marker-char op1 how-to) (or op1 (setq op1 operation)) (let* ((fn-list (dired-get-marked-files nil arg)) (rfn-list (mapcar #'dired-make-relative fn-list)) (dired-one-file ; fluid variable inside dired-create-files (and (consp fn-list) (null (cdr fn-list)) (car fn-list))) (target-dir (dired-dwim-target-directory)) (default (and dired-one-file (not dired-dwim-target) ; Bug#25609 (expand-file-name (file-name-nondirectory (car fn-list)) target-dir))) (defaults (dired-dwim-target-defaults fn-list target-dir)) (target (expand-file-name ; fluid variable inside dired-create-files (minibuffer-with-setup-hook (lambda () (set (make-local-variable 'minibuffer-default-add-function) nil) (setq minibuffer-default defaults)) (dired-mark-read-file-name (concat (if dired-one-file op1 operation) " %s to: ") target-dir op-symbol arg rfn-list default)))) (into-dir (cond ((null how-to) ;; Allow users to change the letter case of ;; a directory on a case-insensitive ;; filesystem. If we don't test these ;; conditions up front, file-directory-p ;; below will return t on a case-insensitive ;; filesystem, and Emacs will try to move ;; foo -> foo/foo, which fails. (if (and (file-name-case-insensitive-p (car fn-list)) (eq op-symbol 'move) dired-one-file (string= (downcase (expand-file-name (car fn-list))) (downcase (expand-file-name target))) (not (string= (file-name-nondirectory (car fn-list)) (file-name-nondirectory target)))) nil (file-directory-p target))) ((eq how-to t) nil) (t (funcall how-to target))))) (if (and (consp into-dir) (functionp (car into-dir))) (apply (car into-dir) operation rfn-list fn-list target (cdr into-dir)) (if (not (or dired-one-file into-dir)) (error "Marked %s: target must be a directory: %s" operation target)) ;; rename-file bombs when moving directories unless we do this: (or into-dir (setq target (directory-file-name target))) (dired-create-files file-creator operation fn-list (if into-dir ; target is a directory ;; This function uses fluid variable target when called ;; inside dired-create-files: (lambda (from) (expand-file-name (file-name-nondirectory from) target)) (lambda (_from) target)) marker-char) (dired target)))) (defun my/dired-rename-follow (orig &optional arg) (when arg (advice-add #'dired-do-create-files :override #'my/dired-do-create-files)) (funcall orig nil) (when arg (advice-remove #'dired-do-create-files #'my/dired-do-create-files))) (advice-add #'dired-do-rename :around #'my/dired-rename-follow) #+end_src ** Elfeed *** Setup feeds #+BEGIN_SRC emacs-lisp ;; Load elfeed-org (use-package elfeed) (use-package elfeed-org) (setq rmh-elfeed-org-files (list "~/.emacs.d/elfeed.org")) (elfeed-org) (setq-default elfeed-search-filter "@1-week-ago +unread -youtube") (define-key elfeed-search-mode-map "U" 'elfeed-search-fetch-visible) (define-key elfeed-search-mode-map "Y" (lambda () (interactive) (elfeed-search-set-filter "+youtube +unread"))) (define-key elfeed-search-mode-map "N" (lambda () (interactive) (elfeed-search-set-filter "@1-day-ago +unread -youtube"))) (define-key elfeed-search-mode-map "h" (lambda () (interactive) (elfeed-search-set-filter nil))) #+END_SRC *** youtube-dl #+begin_src emacs-lisp (defun elfeed-show-youtube-dl () "Download the current entry with youtube-dl." (interactive) (pop-to-buffer (youtube-dl (elfeed-entry-link elfeed-show-entry)))) (cl-defun elfeed-search-youtube-dl (&key slow) "Download the current entry with youtube-dl." (interactive) (let ((entries (elfeed-search-selected))) (dolist (entry entries) (if (null (youtube-dl (elfeed-entry-link entry) :title (elfeed-entry-title entry) :slow slow)) (message "Entry is not a YouTube link!") (message "Downloading %s" (elfeed-entry-title entry))) (elfeed-untag entry 'unread) (elfeed-search-update-entry entry) (unless (use-region-p) (forward-line))))) (define-key elfeed-search-mode-map "d" 'elfeed-search-youtube-dl) (setq youtube-dl-directory "~/big_files/Videos/youtube-dl") #+end_src *** Youtube show thumbnail #+begin_src emacs-lisp (use-package dash) (defun elfeed-entries-from-atom (url xml) "Turn parsed Atom content into a list of elfeed-entry structs." (let* ((feed-id url) (protocol (url-type (url-generic-parse-url url))) (namespace (elfeed-url-to-namespace url)) (feed (elfeed-db-get-feed feed-id)) (title (elfeed-cleanup (xml-query* (feed title *) xml))) (author (elfeed-cleanup (xml-query* (feed author name *) xml))) (xml-base (or (xml-query* (feed :base) xml) url)) (autotags (elfeed-feed-autotags url))) (setf (elfeed-feed-url feed) url (elfeed-feed-title feed) title (elfeed-feed-author feed) author) (cl-loop for entry in (xml-query-all* (feed entry) xml) collect (let* ((title (or (xml-query* (title *) entry) "")) (xml-base (elfeed-update-location xml-base (xml-query* (:base) (list entry)))) (anylink (xml-query* (link :href) entry)) (altlink (xml-query* (link [rel "alternate"] :href) entry)) (link (elfeed--fixup-protocol protocol (elfeed-update-location xml-base (or altlink anylink)))) (date (or (xml-query* (published *) entry) (xml-query* (updated *) entry) (xml-query* (date *) entry) (xml-query* (modified *) entry) ; Atom 0.3 (xml-query* (issued *) entry))) ; Atom 0.3 (author-name (or (xml-query* (author name *) entry) ;; Dublin Core (xml-query* (creator *) entry))) (author-email (xml-query* (author email *) entry)) (author (cond ((and author-name author-email) (format "%s <%s>" author-name author-email)) (author-name))) (categories (xml-query-all* (category :term) entry)) (content (elfeed--atom-content entry)) (id (or (xml-query* (id *) entry) link (elfeed-generate-id content))) (type (or (xml-query* (content :type) entry) (xml-query* (summary :type) entry) "")) (tags (elfeed-normalize-tags autotags elfeed-initial-tags)) (content-type (if (string-match-p "html" type) 'html nil)) (etags (xml-query-all* (link [rel "enclosure"]) entry)) (thumb (xml-query* (group thumbnail :url) entry)) (enclosures (cl-loop for enclosure in etags for wrap = (list enclosure) for href = (xml-query* (:href) wrap) for type = (xml-query* (:type) wrap) for length = (xml-query* (:length) wrap) collect (list href type length))) (db-entry (elfeed-entry--create :title (elfeed-cleanup title) :feed-id feed-id :id (cons namespace (elfeed-cleanup id)) :link (elfeed-cleanup link) :tags tags :date (or (elfeed-float-time date) (float-time)) :content content :enclosures enclosures :content-type content-type :meta `(,@(when author (list :author author)) ,@(when categories (list :categories categories)) ,@(when thumb (list :thumbnail (elfeed-get-thumbnail thumb))))))) (setq debug/entry db-entry) (dolist (hook elfeed-new-entry-parse-hook) (funcall hook :atom entry db-entry)) db-entry)))) (defun elfeed-insert-sliced-thumbnail (orig-fun entry) (let ((thumbnail (elfeed-meta entry :thumbnail))) (if (null thumbnail) (funcall orig-fun entry) (insert-sliced-image (create-image thumbnail 'imagemagick nil :height 150) nil nil 4) (delete-backward-char 1) (previous-line) (previous-line) (end-of-line) (let* ((date (elfeed-search-format-date (elfeed-entry-date entry))) (title (or (elfeed-meta entry :title) (elfeed-entry-title entry) "")) (title-faces (elfeed-search--faces (elfeed-entry-tags entry))) (feed (elfeed-entry-feed entry)) (feed-title (when feed (or (elfeed-meta feed :title) (elfeed-feed-title feed)))) (tags (mapcar #'symbol-name (elfeed-entry-tags entry))) (tags-str (mapconcat (lambda (s) (propertize s 'face 'elfeed-search-tag-face)) tags ",")) (title-width (- (window-width) 10 elfeed-search-trailing-width)) (title-column (elfeed-format-column title (elfeed-clamp elfeed-search-title-min-width title-width elfeed-search-title-max-width) :left))) (insert " " (propertize title-column 'face title-faces 'kbd-help title) " ") (next-line) (insert " " (propertize date 'face 'elfeed-search-date-face) " ") (when feed-title (insert (propertize feed-title 'face 'elfeed-search-feed-face) " ")) (when tags (insert "(" tags-str ")"))) (next-line) (end-of-line)))) (defun elfeed-insert-sliced-thumbnail (orig-fun entry) (let ((thumbnail (elfeed-meta entry :thumbnail))) (if (null thumbnail) (funcall orig-fun entry) (insert-sliced-image (create-image thumbnail 'imagemagick nil :height 150) nil nil 4) (delete-backward-char 1) (previous-line) (previous-line) (end-of-line) (let* ((date (elfeed-search-format-date (elfeed-entry-date entry))) (title (or (elfeed-meta entry :title) (elfeed-entry-title entry) "")) (title-faces (elfeed-search--faces (elfeed-entry-tags entry))) (feed (elfeed-entry-feed entry)) (feed-title (when feed (or (elfeed-meta feed :title) (elfeed-feed-title feed)))) (tags (mapcar #'symbol-name (elfeed-entry-tags entry))) (tags-str (mapconcat (lambda (s) (propertize s 'face 'elfeed-search-tag-face)) tags ",")) (title-width (- (window-width) 10 elfeed-search-trailing-width)) (title-column (elfeed-format-column title (elfeed-clamp elfeed-search-title-min-width title-width elfeed-search-title-max-width) :left))) (insert " " (propertize title-column 'face title-faces 'kbd-help title) " ") (next-line) (insert " " (propertize date 'face 'elfeed-search-date-face) " ") (when feed-title (insert (propertize feed-title 'face 'elfeed-search-feed-face) " ")) (when tags (insert "(" tags-str ")"))) (next-line) (end-of-line)))) (defun elfeed-insert-thumbnail (entry) (let ((thumbnail (elfeed-meta entry :thumbnail))) (if (null thumbnail) (insert "") (insert " ") (insert-image (create-image thumbnail 'imagemagick nil :height 150)) (insert " ")))) (advice-add 'elfeed-search-print-entry--default :before #'elfeed-insert-thumbnail) (defvar elfeed-link-org-capture nil) (defun elfeed-show-insert-thumbnail () (let ((inhibit-read-only t) (thumbnail (elfeed-meta elfeed-show-entry :thumbnail))) (if (null thumbnail) (insert "") (insert-image (create-image thumbnail 'imagemagick nil :height 150)) (insert "\n")) (goto-char (point-min)) (setq elfeed-link-org-capture (format "[[%s][%s]] :%s:%s:" (elfeed-entry-link elfeed-show-entry) (elfeed-entry-title elfeed-show-entry) (elfeed-meta elfeed-show-entry :author) (string-join (mapcar #'symbol-name (elfeed-entry-tags elfeed-show-entry)) ":"))))) (advice-add 'elfeed-show-refresh--mail-style :after #'elfeed-show-insert-thumbnail) (defun elfeed-get-thumbnail (url) (let* ((file (--> url (split-string it "/") (nth 4 it) (concat it ".jpg"))) (img-url (replace-regexp-in-string "/hqdefault.jpg$" "/mqdefault.jpg" url)) (img-folder (--> "images" (expand-file-name it elfeed-db-directory) (file-name-as-directory it))) (filepath (concat img-folder file))) (unless (file-directory-p img-folder) (make-directory img-folder)) (unless (file-exists-p filepath) (start-process-shell-command "wget" nil (format "wget %s -O %s" img-url filepath))) filepath)) #+end_src * Email ** Gnus #+BEGIN_SRC emacs-lisp (add-hook 'gnus-group-mode-hook 'gnus-topic-mode) (setq user-mail-address "bensonchu457@gmail.com" user-full-name "Benson Chu") (setq gnus-select-method '(nnmaildir "gmail" (directory "~/.offlineimap_mail/personal") (directory-files nnheader-directory-files-safe) (get-new-mail nil))) (setq gnus-secondary-select-methods '((nnmaildir "work" (directory "~/.offlineimap_mail/work") (directory-files nnheader-directory-files-safe) (get-new-mail nil)))) ;; (setq gnus-select-method ;; '(nnimap "Local" ;; (nnimap-address "localhost") ;; (nnimap-stream network) ;; (nnimap-server-port 143))) ;; (setq gnus-select-method ;; '(nnimap "gmail" ;; (nnimap-address "imap.gmail.com") ;; (nnimap-server-port "imaps") ;; (nnimap-stream ssl) ;; (nnimap-authinfo-file "~/.emacs.d/secrets/.authinfo.gpg"))) (setq gnus-mark-article-hook nil) (gnus-add-configuration '(article (horizontal 1.0 (vertical 25 (group 1.0)) (vertical 1.0 (summary 0.25 point) (article 1.0))))) (gnus-add-configuration '(summary (horizontal 1.0 (vertical 25 (group 1.0)) (vertical 1.0 (summary 1.0 point))))) ;;(setq gnus-summary-line-format "%U%R%z%I%(%[%4L: %-23,23f%]%) %s\n") (setq gnus-summary-line-format "%d %U%R%z%I%(%[%4L: %-23,23f%]%) %s\n") #+END_SRC ** mu4e #+BEGIN_SRC emacs-lisp# (unless (eq system-type 'windows-nt) (require 'mu4e) (add-to-list 'mu4e-view-actions '("ViewInBrowser" . mu4e-action-view-in-browser) t) ;; (global-set-key (kbd "") 'mu4e) (setq mu4e-maildir "~/.offlineimap_mail" mu4e-sent-folder "/personal/[Gmail].Sent Mail" mu4e-drafts-folder "/personal/[Gmail].Drafts" mu4e-refile-folder "/personal/[Gmail].Archive") (defvar my-mu4e-account-alist '(("Gmail" (mu4e-sent-folder "/work/Sent Mail") (mu4e-drafts-folder "/Gmail/[Gmail].Drafts") (mu4e-refile-folder "/Gmail/[Gmail].Archive") (user-mail-address "bensonchu457@gmail.com") (smtpmail-default-smtp-server "smtp.gmail.com") (smtpmail-smtp-user "bensonchu457") (smtpmail-smtp-server "smtp.gmail.com")) ("work" (mu4e-sent-folder "/work/Sent") (mu4e-drafts-folder "/work/Drafts") (mu4e-refile-folder "/work/Archive") (user-mail-address "bchu3@uh.edu") (smtpmail-default-smtp-server "smtp.account2.example.com") (smtpmail-smtp-user "bchu3") (smtpmail-smtp-server "smtp.account2.example.com"))))) ;;(defun my-mu4e-set-account () ;; "Set the account for composing a message." ;; (let* ((account ;; (if mu4e-compose-parent-message ;; (let ((maildir (mu4e-message-field mu4e-compose-parent-message :maildir))) ;; (string-match "/\\(.*?\\)/" maildir) ;; (match-string 1 maildir)) ;; (completing-read (format "Compose with account: (%s) " ;; (mapconcat #'(lambda (var) (car var)) ;; my-mu4e-account-alist "/")) ;; (mapcar #'(lambda (var) (car var)) my-mu4e-account-alist) ;; nil t nil nil (caar my-mu4e-account-alist)))) ;; (account-vars (cdr (assoc account my-mu4e-account-alist)))) ;; (if account-vars ;; (mapc #'(lambda (var) ;; (set (car var) (cadr var))) ;; account-vars) ;; (error "No email account found")))) ;; (add-hook 'mu4e~headers-jump-to-maildir 'my-mu4e-set-account) #+END_SRC * New ** Time to game! #+BEGIN_SRC emacs-lisp (defvar my/games '("desmume" "mednaffe" "dolphin-emu" "m64py" "citra-qt" "steam " "th12")) (defun time-to-game () (interactive) (let ((selection (completing-read "What would you like to play? " my/games))) (launch-program selection))) #+END_SRC ** Winner Mode #+BEGIN_SRC emacs-lisp (require 'winner) (winner-mode) #+END_SRC ** Skewer Mode (web development) #+BEGIN_SRC emacs-lisp (use-package js2-mode) (add-to-list 'auto-mode-alist '("\\.js\\'" . js2-mode)) (use-package skewer-mode) (add-hook 'js2-mode-hook 'skewer-mode) (add-hook 'css-mode-hook 'skewer-css-mode) (add-hook 'html-mode-hook 'skewer-html-mode) #+END_SRC ** AUR PKGBUILD #+BEGIN_SRC emacs-lisp (use-package pkgbuild-mode) #+END_SRC ** Eyebrowse #+BEGIN_SRC emacs-lisp (use-package eyebrowse :init (setq eyebrowse-keymap-prefix (kbd "C-c w")) :config (eyebrowse-mode) (global-set-key (kbd "C->") 'eyebrowse-next-window-config) (global-set-key (kbd "C-<") 'eyebrowse-prev-window-config)) #+END_SRC ** Writing mode #+BEGIN_SRC emacs-lisp (defun org-writing-mode () (interactive) (setq org-bullets-bullet-list (quote (" "))) (buffer-face-set '(:family "ETBookOT"))) #+END_SRC ** arch-linux #+begin_src emacs-lisp (use-package arch-packer) #+end_src ** Compile java run test #+begin_src emacs-lisp (defun compile-java () (interactive) (let ((fname (file-name-nondirectory buffer-file-name))) (shell-command (format "javac %s" fname)) (message (shell-command-to-string (format "java %s" (substring fname 0 (- (length fname) 5))))))) (global-set-key (kbd "C-") 'compile-java) #+end_src ** wtf #+begin_src emacs-lisp (use-package wtf) #+end_src ** kdeconnect #+begin_src emacs-lisp (use-package kdeconnect) (setq kdeconnect-devices "ddcc003536dcf16d") (setq kdeconnect-active-device "ddcc003536dcf16d") #+end_src ** Purpose-mode #+begin_src emacs-lisp# (use-package window-purpose) (add-to-list 'purpose-user-mode-purposes '(exwm-mode . research)) (add-to-list 'purpose-user-mode-purposes '(js2-mode . dev)) (purpose-compile-user-configuration) (purpose-mode) #+end_src ** eosd #+begin_src emacs-lisp ;; (add-to-list 'load-path ;; "~/.emacs.d/submodule/eosd") ;; (require 'eosd) #+end_src ** leetcode #+begin_src emacs-lisp (use-package ctable) (use-package names) (add-to-list 'load-path "~/.emacs.d/submodule/leetcode-emacs") (require 'leetcode) (setq leetcode-path "~/MEGA/personal/programming_problems/Leetcode" leetcode-language "java") #+end_src ** Ace-window #+begin_src emacs-lisp (use-package ace-window) (defhydra window-management-hydra (*root-map* "C-w") "Manage window splits" ("2" split-window-below) ("3" split-window-right) ("h" windmove-left) ("j" windmove-down) ("k" windmove-up) ("l" windmove-right) ("+" enlarge-window-horizontally) ("-" shrink-window-horizontally) ("M-+" enlarge-window) ("M--" shrink-window) ("x" delete-window) ("q" nil)) #+end_src ** function to set tabwith #+begin_src emacs-lisp (defun my/TABS (num) (interactive "p") (setq tab-width (if (= num 1) 8 num))) #+end_src ** bookmark+ #+begin_src emacs-lisp (add-to-list 'load-path "~/.emacs.d/submodule/bookmark-plus") (require 'bookmark+) #+end_src ** Custom bookmarks location #+begin_src emacs-lisp# (bookmark-load "~/.emacs.d/my-bookmarks") (defun my/bookmark-set (&optional name no-overwrite) (interactive (list nil current-prefix-arg)) (bookmark-set name no-overwrite) (let* ((buffer (find-file-noselect "~/.emacs.d/my-bookmarks")) (bookmark (car bookmark-alist)) (bookmark-name (car bookmark)) (bookmark-file (and (buffer-file-name) (file-name-nondirectory (buffer-file-name))))) (with-current-buffer buffer (goto-char (point-min)) (when (not (or (save-excursion (re-search-forward bookmark-name)) (and bookmark-file (save-excursion (re-search-forward bookmark-file))))) (re-search-forward "(") (insert (pp bookmark)) (save-buffer) (kill-buffer))))) ;; (global-set-key (kbd "C-x r m") #'my/bookmark-set) #+end_src ** Subtitles editing #+begin_src emacs-lisp (add-to-list 'load-path "~/.emacs.d/submodule/subed/subed") (require 'subed) ;; Disable automatic movement of point by default (add-hook 'subed-mode-hook 'subed-disable-sync-point-to-player) ;; Break lines automatically while typing (add-hook 'subed-mode-hook 'turn-on-auto-fill) ;; Break lines at 50 characters (add-hook 'subed-mode-hook (lambda () (setq-local fill-column 50))) #+end_src ** docker #+begin_src emacs-lisp (use-package docker) (global-set-key (kbd "C-x C-d") #'docker) #+end_src ** compilation buffer in same window #+begin_src emacs-lisp ;; (add-to-list 'display-buffer-alist ;; '("\\*compilation\\*" (display-buffer-reuse-window . display-buffer-same-window) )) (add-to-list 'same-window-buffer-names "*compilation*") ;; (setq display-buffer-alist (remove-if (lambda (x) (string= "\\*compilation\\*" (car x))) display-buffer-alist)) #+end_src ** compilation scroll #+begin_src emacs-lisp (setq compilation-scroll-output t) #+end_src ** google-it with qutebrowser #+begin_src emacs-lisp (require 'url-util) (defun my/google-it () (interactive) (let* ((resp (read-from-minibuffer "What is your query? ")) (cleaned-resp (url-hexify-string resp))) (launch-program (format "qutebrowser \"https://google.com/search?q=%s\"" cleaned-resp)))) (define-key *root-map* (kbd "g") #'my/google-it) #+end_src ** 256-color :fix: #+begin_src emacs-lisp# (use-package eterm-256color) (add-hook 'term-mode-hook #'eterm-256color-mode) #+end_src ** read only buffers in view-mode #+begin_src emacs-lisp (setq view-read-only t) #+end_src ** hyperbole #+begin_src emacs-lisp (use-package hyperbole) ;; I don't care about smart scrolling in org mode, unless I actually do (defun my/smart-scroll-up (old) (if (eq major-mode 'org-mode) (org-meta-return) (funcall old))) (advice-add #'smart-scroll-up :around #'my/smart-scroll-up) #+end_src ** Go to work #+begin_src emacs-lisp (defvar my/working nil) (defvar my/dev-agenda nil) (defun toggle-working () (interactive) (setq my/working (not my/working)) (cond (my/working (define-key *firefox-map* (kbd "f") nil) (setq my/dev-agenda (assoc "d" org-agenda-custom-commands)) (setq org-agenda-custom-commands (delq (assoc "d" org-agenda-custom-commands) org-agenda-custom-commands)) (message "Back to work!")) ((not my/working) (define-key *firefox-map* (kbd "f") (quickrun-lambda "firefox" "firefox")) (add-to-list 'org-agenda-custom-commands my/dev-agenda) (message "Break time!")))) (global-set-key (kbd "s-w") #'toggle-working) #+end_src ** centaur tabs #+begin_src emacs-lisp (use-package centaur-tabs) #+end_src ** solaire-mode #+begin_src emacs-lisp (use-package solaire-mode) #+end_src ** tramp things #+begin_src emacs-lisp (use-package docker-tramp) (use-package tramp-hdfs) #+end_src ** CASA Schedule #+begin_src emacs-lisp (defvar my/schedule "https://uofh-my.sharepoint.com/:x:/g/personal/nsingh29_cougarnet_uh_edu/ERfp7g_6FbFAsxIlV0YP1goB9iXnUcTm__kTvakvXmvcvQ?rtime=-JcPFVIj10g") (defun my/view-casa-schedule () (interactive) (funcall browse-url-browser-function my/schedule)) #+end_src ** Vivaldi #+begin_src emacs-lisp (defun browse-url-vivaldi (url &optional new-window) (interactive (browse-url-interactive-arg "URL: ")) (setq url (browse-url-encode-url url)) (let* ((process-environment (browse-url-process-environment))) (apply 'start-process (concat "vivaldi " url) nil "vivaldi-stable" (list url)))) (setq browse-url-browser-function #'browse-url-firefox) #+end_src ** Google Translate #+begin_src emacs-lisp (use-package google-translate) #+end_src ** read-identifier too slow #+begin_src emacs-lisp (add-to-list 'xref-prompt-for-identifier 'xref-find-references 'append) #+end_src ** workgroups2 #+begin_src emacs-lisp ;; (use-package workgroups2) ;; (setq wg-prefix-key (kbd "C-c z")) ;; (setq wg-session-file "~/.emacs.d/.emacs_workgroups") (require 'ivy-window-configurations) (define-key *root-map* (kbd "b") #'iwc-switch-to-wc) (define-key *root-map* (kbd "R") #'iwc-rename) (iwc-mode) ;; (define-key *root-map* (kbd "u") #'wg-undo-wconfig-change) ;; (define-key *root-map* (kbd "q") #'wg-kill-workgroup) ;; (define-key *root-map* (kbd "Q") #'wg-delete-other-workgroups) ;; (setq wg-emacs-exit-save-behavior nil ;; wg-workgroups-mode-exit-save-behavior nil) ;; ;; Advice for frames, don't switch to an active workgroup ;; (defun get-active-workgroups () ;; (loop for frame in exwm-workspace--list ;; unless (eq (selected-frame) frame) ;; collect (with-selected-frame frame ;; (wg-workgroup-name (wg-current-workgroup))))) ;; (defun wg-dont-switch-to-active (orig &optional workgroup noerror) ;; (interactive) ;; (if workgroup ;; (funcall orig workgroup noerror) ;; (let ((active (get-active-workgroups)) ;; (to-switch (wg-read-workgroup-name))) ;; (if (member to-switch active) ;; (message "Workgroup \"%s\" already active" to-switch) ;; (funcall orig to-switch noerror))))) ;; (advice-add #'wg-switch-to-workgroup ;; :around ;; #'wg-dont-switch-to-active) #+end_src ** opml to elfeed-org #+begin_src emacs-lisp (defun convert-opml-feed-to-org-mode () (interactive) (goto-char (point-min)) (save-excursion (perform-replace "><" ">\n<" nil nil nil nil)) (save-excursion (keep-lines "\\(?:^\\)")) (perform-replace "\\(?:^\\)" "*** [[\\2][\\1]]" nil t nil)) (defun delete-org-headings () (interactive) (goto-char (point-min)) (let ((lines '())) (while (and (outline-next-heading) (not (eobp))) (let ((heading (org-get-heading t t t t))) (if (not (member heading lines)) (push heading lines) (org-cut-subtree) (outline-previous-heading)))))) #+end_src * Broken ** Wunderlist #+BEGIN_SRC emacs-lisp# (use-package org-wunderlist) (save-excursion (let ((filename "~/.emacs.d/wunderlist.el")) (if (not (file-exists-p filename)) (message "Wunderlist secret file missing") (set-buffer (find-file-noselect filename)) (let ((var (eval (read (buffer-string))))) (setq org-wunderlist-client-id (car var) org-wunderlist-token (cadr var))) (kill-buffer)))) (setq org-wunderlist-file "~/MEGA/org/agenda/Wunderlist.org" org-wunderlist-dir "~/MEGA/org/agenda/org-wunderlist/") #+END_SRC ** poshint #+begin_src emacs-lisp# (use-package pophint) #+end_src ** buffer-time-tracking :fix: #+begin_src emacs-lisp# (use-package switch-buffer-functions) ;;(load "switch-buffer-functions-autoloads.el") (defun my/insert-into-buffers-csv (str str2 symb str3) (let* ((buffer (find-file-noselect "~/MEGA/org/agenda/buffer_times.csv")) (inhibit-message t)) (with-current-buffer buffer (goto-char (point-max)) (insert (format-time-string "%Y-%m-%d %H:%M:%S" (current-time))) (insert "," str "," (if str2 str2 "") "," str3 "," (if symb (symbol-name symb) "")) (insert "\n") (save-buffer)))) (defun my/record-buffer-switch (prev cur) (let* (obuffer-name buffer-name buffer-fname buffer-mode buffer-def-dir) (with-current-buffer cur (setq buffer-name (buffer-name) buffer-fname (buffer-file-name) buffer-mode major-mode buffer-def-dir default-directory)) (when (buffer-live-p prev) (with-current-buffer prev (setq obuffer-name (buffer-name)))) (when (and (not (string= buffer-name " *Minibuf-1*")) ;; (or (not obuffer-name) (not (string= obuffer-name " *Minibuf-1*"))) ) (my/insert-into-buffers-csv buffer-name buffer-fname buffer-mode buffer-def-dir)))) ;; (add-hook 'switch-buffer-functions ;; 'my/record-buffer-switch) (defun leaving-computer () (interactive) (my/insert-into-buffers-csv "Inactive" "" nil "") (org-clock-out nil t) (message "Computer is now inactive!")) #+end_src * Disabled ** nnreddit #+BEGIN_SRC emacs-lisp# (use-package nnredit "~/.emacs.d/nnreddit/nnreddit.el") (add-to-list 'gnus-secondary-select-methods '(nnreddit "")) #+END_SRC ** xwidget #+BEGIN_SRC emacs-lisp# (define-key xwidget-webkit-mode-map [mouse-4] 'xwidget-webkit-scroll-down) (define-key xwidget-webkit-mode-map [mouse-5] 'xwidget-webkit-scroll-up) #+END_SRC ** i3wm interaction #+BEGIN_SRC emacs-lisp# (use-package i3wm) (defun insert-mode () (interactive) (i3wm-command "mode insert")) (global-set-key (kbd "M-\"") 'insert-mode) #+END_SRC ** Cyberpunk Theme #+BEGIN_SRC #emacs-lisp (load-theme 'cyberpunk t) (use-package moe-theme) (moe-dark) (powerline-moe-theme) #+END_SRC ** Wanderlust #+BEGIN_SRC emacs-lisp# (autoload 'wl "wl" "Wanderlust" t) #+END_SRC ** linum #+BEGIN_SRC emacs-lisp# (use-package linum) (linum-relative-global-mode) (setq linum-relative-current-symbol "") ;(setq linum-format ; (lambda (line) ; (propertize (format (let ((w (length (number-to-string (count-lines (point-min) (point-max)))))) ; (concat "%" (number-to-string w) "d ")) ; line) ; 'face ; 'linum))) ;(setq linum-relative-format "%3s\u2502 ") #+END_SRC ** CTD Minor Mode *** Keybinding #+BEGIN_SRC emacs-lisp# (use-package multi-term) (define-minor-mode ctd-mode "This is the mode for the CoderTillDeath" :init-value t :lighter " ctd" :keymap (let ((map (make-sparse-keymap))) (define-key map (kbd "M-e") 'launch-program) (define-key map (kbd "C-x p") 'launch-program) (define-key map (kbd "M-`") 'multi-term) (define-key map (kbd "M-1") 'windresize) map)) (ctd-mode 1) #+END_SRC *** Precedence #+BEGIN_SRC emacs-lisp# (add-hook 'after-load-functions 'ctd-mode-priority) (defun ctd-mode-priority (_file) "Try to ensure that my keybindings retain priority over other minor modes. Called via the `after-load-functions' special hook." (unless (eq (caar minor-mode-map-alist) 'ctd-mode) (let ((mykeys (assq 'ctd-mode minor-mode-map-alist))) (assq-delete-all 'ctd-mode minor-mode-map-alist) (add-to-list 'minor-mode-map-alist mykeys)))) #+END_SRC ** Screw delete #+BEGIN_SRC emacs-lisp# (global-set-key (kbd "C-d") 'delete-backward-char) (global-set-key (kbd "M-d") 'backward-kill-word) #+END_SRC ** Custom Journal Attempt 1 #+BEGIN_SRC emacs-lisp# (defvar yearly-theme "Insight") (defun insert-time-stamp () (insert "** " (format-time-string "%A, %x"))) (defun current-date-exists? () (save-excursion (let ((match (re-search-forward (format-time-string "\\(* %A, %x\\)") nil t))) (match-beginning 1)))) (defun add-date () (search-forward "* Journal") (beginning-of-line) (org-narrow-to-subtree) (let ((point (current-date-exists?))) (if point (goto-char point) (goto-char (point-max)) (insert-time-stamp))) (widen)) (defun add-weekly-journal-entry () (add-date)) (defun org-capture-function () (unless (file-exists-p "~/MEGA/org/entries/review/current.org") (create-weekly-review-file)) (set-buffer (org-capture-target-buffer "~/MEGA/org/entries/review/current.org")) (let ((m (point-marker))) (set-buffer (marker-buffer m)) (org-capture-put-target-region-and-position) (widen) (goto-char m) (set-marker m nil) (add-weekly-journal-entry))) (defun create-weekly-review-file () (save-excursion (let ((entry-path "~/MEGA/org/entries/review/current.org")) (find-file-other-window entry-path) (insert (format "#+TITLE: Year of %s, week %s\n\n" yearly-theme (format-time-string "%V")) "* Log\n" "* Journal\n") (save-buffer) (kill-buffer)))) (defun weekly-review () (interactive) (let ((entry-path "~/MEGA/org/entries/review/current.org")) (find-file entry-path) (goto-char (point-max)) (insert "\n* Review\n"))) (defun wr/done () (interactive) (save-buffer) (kill-buffer) (unless (file-directory-p (format-time-string "~/MEGA/org/entries/review/%Y")) (make-directory (format-time-string "~/MEGA/org/entries/review/%Y"))) (rename-file "~/MEGA/org/entries/review/current.org" (format-time-string "~/MEGA/org/entries/review/%Y/Year of Insight, Week %V.org") t) (create-weekly-review-file)) #+END_SRC ** Custom Journal Attempt 2 #+BEGIN_SRC emacs-lisp# (defvar yearly-theme "Surpass") (defun completed-tags-search (start-date end-date) (let ((org-agenda-overriding-header "* Log") (tag-search (concat (format "TODO=\"DONE\"&CLOSED>=\"[%s]\"&CLOSED<=\"[%s]\"" start-date end-date)))) (org-tags-view nil tag-search))) (defun get-tasks-from (start-date end-date) (let (string) (save-window-excursion (completed-tags-search start-date end-date) (setq string (mapconcat 'identity (mapcar (lambda (a) (concat "**" a)) (butlast (cdr (split-string (buffer-string) "\n")) 1)) "\n")) (kill-buffer)) string)) (defun get-journal-entries-from (start-date end-date) (let ((string "") match) (save-window-excursion (switch-to-buffer (find-file "~/MEGA/org/entries/journal.gpg")) (goto-char (point-min)) (while (setq match (re-search-forward "^\\*\\*\\* \\(2[0-9]\\{3\\}-[0-9]\\{2\\}-[0-9]\\{2\\}\\) \\w+$" nil t)) (let ((date (match-string 1))) (when (and (org-time< start-date date) (or (not end-date) (org-time< date end-date))) (org-narrow-to-subtree) (org-shiftmetaleft) (setq string (concat string "\n" (buffer-string))) (org-shiftmetaright) (widen)))) (not-modified) (kill-buffer)) string)) (defun generate-view-between (start-date end-date) (let ((start-date (or start-date (org-read-date))) (end-date (or end-date (org-read-date))) (org-agenda-skip-archived-trees nil)) (get-buffer-create "review.org") (switch-to-buffer "review.org") (org-mode) (insert (format "#+Title of %s, Week %s\n\n" yearly-theme (format-time-string "%V"))) (insert "* Log\n") (insert (get-tasks-from start-date end-date)) (insert "\n* Journal")) (insert (get-journal-entries-from start-date end-date)) (when (> (funcall outline-level) 1) (outline-up-heading 2)) (org-cycle) (org-cycle) (goto-char (point-max))) (defun generate-view-from () (interactive) (let ((date (org-read-date))) (generate-view-between date (org-read-date nil nil "")))) (defun generate-weekly-view () (interactive) (let ((start-date (org-read-date nil nil "-1w")) (end-date (org-read-date nil nil ""))) (generate-view-between start-date end-date))) (defun weekly-review () (interactive) (generate-weekly-view) (goto-char (point-max)) (insert "\n* Review\n")) (defun offday-review () (interactive) (generate-view-from) (goto-char (point-max)) (insert "\n* Review\n")) (defun wr/done () (interactive) (write-file (concat "~/MEGA/org/entries/review/" (format-time-string "%Y/") (format "Year of %s, Week " yearly-theme) (format-time-string "%V") ".org")) (kill-buffer)) (defun view-reports () (interactive) (dired (format-time-string "~/MEGA/org/entries/review/%Y/"))) #+END_SRC ** Norang Projects code #+BEGIN_SRC emacs-lisp# (require 'org-habit) (defun bh/find-project-task () "Move point to the parent (project) task if any" (save-restriction (widen) (let ((parent-task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) (while (org-up-heading-safe) (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) (setq parent-task (point)))) (goto-char parent-task) parent-task))) (defun bh/is-project-p () "Any task with a todo keyword subtask" (or (equal (org-get-todo-state) "PROJECT") (save-restriction (widen) (let ((subtree-end (save-excursion (org-end-of-subtree t))) (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1)) has-subtask has-task) (save-excursion (forward-line 1) (while (and (not has-subtask) (< (point) subtree-end) (re-search-forward "^\*+ " subtree-end t)) (when (member (org-get-todo-state) org-todo-keywords-1) (setq has-subtask t) (when (not (equal (org-get-todo-state) "DONE")) (setq has-task t))))) (and is-a-task (or has-task (and has-subtask (equal "TODO" (org-get-todo-state))))))))) (defun bh/is-project-subtree-p () "Any task with a todo keyword that is in a project subtree. Callers of this function already widen the buffer view." (let ((task (save-excursion (org-back-to-heading 'invisible-ok) (point)))) (save-excursion (bh/find-project-task) (if (equal (point) task) nil t)))) (defun bh/is-task-p () "Any task with a todo keyword and no subtask" (save-restriction (widen) (let ((has-subtask) (subtree-end (save-excursion (org-end-of-subtree t))) (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) (save-excursion (forward-line 1) (while (and (not has-subtask) (< (point) subtree-end) (re-search-forward "^\*+ " subtree-end t)) (when (member (org-get-todo-state) org-todo-keywords-1) (setq has-subtask t)))) (and is-a-task (or (equal (org-get-todo-state) "ONE") (not has-subtask)))))) (defun my/is-standalone-task-p () (and (my/is-a-task) (not (bh/is-subproject-p)))) (defun bh/is-next-task-p () (and (bh/is-task-p) (or (equal (org-get-todo-state) "NEXT") (and (equal (org-get-todo-state) "TODO") (or (org-get-scheduled-time (point)) (org-get-deadline-time (point))))))) (defun bh/is-subproject-p () "Any task which is a subtask of another project" (let ((is-subproject) (is-a-task (member (nth 2 (org-heading-components)) org-todo-keywords-1))) (save-excursion (while (and (not is-subproject) (org-up-heading-safe)) (when (member (nth 2 (org-heading-components)) org-todo-keywords-1) (setq is-subproject t)))) (and is-a-task is-subproject))) (defvar memoized-stuck-function nil "DO NOT SETQ. Use in agenda views") (defun my/make-memoized-stuck-projects () (memoize (lambda (point) (message "Hello, world!") (my/is-stuck-project-p)))) (defun my/is-stuck-project-p () (let ((subtree-end (save-excursion (org-end-of-subtree t))) has-next has-stuck-project) (save-restriction (save-excursion (while (and (or (not has-next) (not has-stuck-project)) (outline-next-heading) (< (point) subtree-end)) (cond ((and (bh/is-project-p) (my/is-stuck-project-p)) (setq has-stuck-project t)) ((or (bh/is-next-task-p) (equal (org-get-todo-state) "WAIT")) (setq has-next t)))))) (and (bh/is-project-p) (or (not has-next) has-stuck-project)))) (defun my/is-inactive-project-p () (let (has-next has-stuck-project) (and (bh/is-project-p) (or (not (member (org-get-todo-state) '("TASK" "PROJECT" "TODO"))) (org-time> (org-entry-get (point) "SCHEDULED") ""))))) (defun my/is-delayed-project-p () (and (bh/is-project-p) (org-entry-get (point) "SCHEDULED") (org-time> (org-entry-get (point) "SCHEDULED") ""))) (defun my/is-ignored-project () ;; Need to finish ) (defun my/is-active-project-p () ;; Need to finish ) (defun bh/list-sublevels-for-projects-indented () "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. This is normally used by skipping functions where this variable is already local to the agenda." (if (marker-buffer org-agenda-restrict-begin) (setq org-tags-match-list-sublevels 'indented) (setq org-tags-match-list-sublevels nil)) nil) (defun bh/list-sublevels-for-projects () "Set org-tags-match-list-sublevels so when restricted to a subtree we list all subtasks. This is normally used by skipping functions where this variable is already local to the agenda." (if (marker-buffer org-agenda-restrict-begin) (setq org-tags-match-list-sublevels t) (setq org-tags-match-list-sublevels nil)) nil) (defvar bh/hide-scheduled-and-waiting-next-tasks t) (defun bh/toggle-next-task-display () (interactive) (setq bh/hide-scheduled-and-waiting-next-tasks (not bh/hide-scheduled-and-waiting-next-tasks)) (when (equal major-mode 'org-agenda-mode) (org-agenda-redo)) (message "%s WAITING and SCHEDULED NEXT Tasks" (if bh/hide-scheduled-and-waiting-next-tasks "Hide" "Show"))) (defun bh/skip-stuck-projects () "Skip trees that are not stuck projects" (save-restriction (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) (when (my/is-stuck-project-p) next-headline)))) (defun my/show-stuck-projects () "Only show subtrees that are stuck projects" ;; (bh/list-sublevels-for-projects-indented) (save-restriction (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))) (subtree-end (save-excursion (org-end-of-subtree t)))) (cond ((my/is-inactive-project-p) subtree-end) ((not (my/is-stuck-project-p)) next-headline))))) (defun my/show-inactive-projects () "Only show subtrees that are stuck projects" ;; (bh/list-sublevels-for-projects-indented) (save-restriction (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))) (subtree-end (save-excursion (org-end-of-subtree t)))) (unless (my/is-inactive-project-p) subtree-end)))) (defun my/show-delayed-projects () "Only show subtrees that are stuck projects" ;; (bh/list-sublevels-for-projects-indented) (save-restriction (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max)))) (subtree-end (save-excursion (org-end-of-subtree t)))) (unless (my/is-delayed-project-p) subtree-end)))) (defun bh/show-active-projects () "Skip trees that are not projects" ;; (bh/list-sublevels-for-projects-indented) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) (unless (and (bh/is-project-p) (not (my/is-stuck-project-p))) next-headline))) (defun bh/skip-non-tasks () "Show non-project tasks. Skip project and sub-project tasks, habits, and project related tasks." (save-restriction (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) (cond ((bh/is-task-p) nil) (t next-headline))))) (defun bh/skip-project-trees-and-habits () "Skip trees that are projects" (save-restriction (widen) (let ((subtree-end (save-excursion (org-end-of-subtree t)))) (cond ((bh/is-project-p) subtree-end) ((org-is-habit-p) subtree-end) (t nil))))) (defun bh/skip-projects-and-habits-and-single-tasks () "Skip trees that are projects, tasks that are habits, single non-project tasks" (save-restriction (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) (cond ((org-is-habit-p) next-headline) ((and bh/hide-scheduled-and-waiting-next-tasks (member "WAITING" (org-get-tags-at))) next-headline) ((bh/is-project-p) next-headline) ((and (bh/is-task-p) (not (bh/is-project-subtree-p))) next-headline) (t nil))))) (defun my/only-next-projects-and-tasks () (save-restriction (widen) (let ((next-headline (save-excursion (or (outline-next-heading) (point-max))))) (cond ((org-is-habit-p) next-headline) ((and bh/hide-scheduled-and-waiting-next-tasks (member "WAITING" (org-get-tags-at))) next-headline) ((bh/is-project-p) next-headline) (t (unless (or (bh/is-next-task-p) (my/is-standalone-task-p)) next-headline)))))) (defun bh/skip-project-tasks-maybe () "Show tasks related to the current restriction. When restricted to a project, skip project and sub project tasks, habits, NEXT tasks, and loose tasks. When not restricted, skip project and sub-project tasks, habits, and project related tasks." (save-restriction (widen) (let* ((subtree-end (save-excursion (org-end-of-subtree t))) (next-headline (save-excursion (or (outline-next-heading) (point-max)))) (limit-to-project (marker-buffer org-agenda-restrict-begin))) (cond ((bh/is-project-p) next-headline) ((org-is-habit-p) subtree-end) ((and (not limit-to-project) (bh/is-project-subtree-p)) subtree-end) ((and limit-to-project (bh/is-project-subtree-p) (member (org-get-todo-state) (list "NEXT"))) subtree-end) (t nil))))) (defun bh/show-non-project-tasks () "Show non-project tasks. Skip project and sub-project tasks, habits, and project related tasks." (save-restriction (widen) (let* ((subtree-end (save-excursion (org-end-of-subtree t)))) (cond ((bh/is-project-p) subtree-end) ((org-is-habit-p) subtree-end) ((bh/is-project-subtree-p) subtree-end) (t nil))))) (defun bh/skip-non-project-tasks () "Show project tasks. Skip project and sub-project tasks, habits, and loose non-project tasks." (save-restriction (widen) (let* ((subtree-end (save-excursion (org-end-of-subtree t))) (next-headline (save-excursion (or (outline-next-heading) (point-max))))) (cond ((bh/is-project-p) next-headline) ((org-is-habit-p) subtree-end) ((and (bh/is-project-subtree-p) (member (org-get-todo-state) (list "NEXT"))) subtree-end) ((not (bh/is-project-subtree-p)) subtree-end) (t nil))))) (defun bh/skip-projects-and-habits () "Skip trees that are projects and tasks that are habits" (save-restriction (widen) (let ((subtree-end (save-excursion (org-end-of-subtree t)))) (cond ((bh/is-project-p) subtree-end) ((org-is-habit-p) subtree-end) (t nil))))) (defun bh/skip-non-subprojects () "Skip trees that are not projects" (let ((next-headline (save-excursion (outline-next-heading)))) (if (bh/is-subproject-p) nil next-headline))) (defun bh/widen () (interactive) (if (equal major-mode 'org-agenda-mode) (progn (org-agenda-remove-restriction-lock) (when org-agenda-sticky (org-agenda-redo))) (widen))) #+END_SRC