Switch from persp to built-in tab-bar
Might as well turn on desktop-save as well, as that seems nicer than reapplying a state and hitting the recentf file list.
This commit is contained in:
parent
bd69943337
commit
9a67d92054
10 changed files with 188 additions and 220 deletions
|
@ -220,7 +220,8 @@ The following /defines/ the rest of my org-mode literate files, that I load late
|
||||||
"ha-org-publishing.org"
|
"ha-org-publishing.org"
|
||||||
"ha-email.org"
|
"ha-email.org"
|
||||||
"ha-aux-apps.org"))
|
"ha-aux-apps.org"))
|
||||||
"ha-dashboard.org"))
|
;; "ha-dashboard.org"
|
||||||
|
))
|
||||||
"List of org files that complete the hamacs project.")
|
"List of org files that complete the hamacs project.")
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ I would like a dedicate perspective to Mastodon, and I would like a leader key s
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(use-package mastodon
|
(use-package mastodon
|
||||||
:config
|
:config
|
||||||
(ha-leader "a m" `("mastodon" . ,(ha-app-perspective "mastodon" #'mastodon)))
|
(ha-leader "a m" `("mastodon" . ,(ha-tab-bar-new "mastodon" #'mastodon)))
|
||||||
|
|
||||||
(defun ha-mastodon-scroll-or-more ()
|
(defun ha-mastodon-scroll-or-more ()
|
||||||
"Scroll a window, and at the end, get more entries in timeline."
|
"Scroll a window, and at the end, get more entries in timeline."
|
||||||
|
@ -175,7 +175,7 @@ I'm thinking the [[https://zevlg.github.io/telega.el/][Telega package]] would be
|
||||||
(when (fboundp 'evil-insert-state)
|
(when (fboundp 'evil-insert-state)
|
||||||
(add-hook 'telega-chat-mode-hook 'evil-insert-state))
|
(add-hook 'telega-chat-mode-hook 'evil-insert-state))
|
||||||
|
|
||||||
(ha-leader "a t" `("telega" . ,(ha-app-perspective "telega" #'telega))))
|
(ha-leader "a t" `("telega" . ,(ha-tab-bar-new "telega" #'telega))))
|
||||||
#+end_src
|
#+end_src
|
||||||
For some reason, you need [[https://github.com/Fanael/rainbow-identifiers][rainbow-identifiers]] to work, oh, I guess the docs state this.
|
For some reason, you need [[https://github.com/Fanael/rainbow-identifiers][rainbow-identifiers]] to work, oh, I guess the docs state this.
|
||||||
|
|
||||||
|
|
352
ha-config.org
352
ha-config.org
|
@ -926,14 +926,13 @@ Since I wasn’t using all the features that [[https://github.com/bbatsov/projec
|
||||||
(ha-leader
|
(ha-leader
|
||||||
"p" '(:ignore t :which-key "projects")
|
"p" '(:ignore t :which-key "projects")
|
||||||
"p W" '("initialize workspace" . ha-workspace-initialize)
|
"p W" '("initialize workspace" . ha-workspace-initialize)
|
||||||
"p n" '("new project space" . ha-project-persp)
|
"p p" '("switch project" . ha-tab-bar-new-project)
|
||||||
|
|
||||||
"p !" '("run cmd in project root" . project-shell-command)
|
"p !" '("run cmd in project root" . project-shell-command)
|
||||||
"p &" '("run cmd async" . project-async-shell-command)
|
"p &" '("run cmd async" . project-async-shell-command)
|
||||||
"p a" '("add new project" . project-remember-projects-under)
|
"p a" '("add new project" . project-remember-projects-under)
|
||||||
"p d" '("dired" . project-dired)
|
"p d" '("dired" . project-dired)
|
||||||
"p k" '("kill project buffers" . project-kill-buffers)
|
"p k" '("kill project buffers" . project-kill-buffers)
|
||||||
"p p" '("switch project" . project-switch-project)
|
|
||||||
"p x" '("remove known project" . project-forget-project)
|
"p x" '("remove known project" . project-forget-project)
|
||||||
|
|
||||||
"p f" '("find file" . project-find-file)
|
"p f" '("find file" . project-find-file)
|
||||||
|
@ -947,205 +946,174 @@ Since I wasn’t using all the features that [[https://github.com/bbatsov/projec
|
||||||
"p s" '("project shell" . project-shell)))
|
"p s" '("project shell" . project-shell)))
|
||||||
#+end_src
|
#+end_src
|
||||||
** Workspaces
|
** Workspaces
|
||||||
A /workspace/ (at least to me) requires a quick jump to a collection of buffer windows organized around a project or task. For this, I'm basing my work on the [[https://github.com/nex3/perspective-el][perspective.el]] project.
|
A /workspace/ (at least to me) requires a quick jump to a collection of buffer windows organized around a project or task. Later versions of Emacs use [[https://www.gnu.org/software/emacs/manual/html_node/emacs/Tab-Bars.html][Tab Bars]] which group windows and buffers in a perspective. The code that follows is a Poor Person’s Workspace package. Also let’s dive into the end section of [[https://www.masteringemacs.org/article/demystifying-emacs-window-manager][Mickey Petersen's essay]] on the subject.
|
||||||
|
|
||||||
I build a Hydra to dynamically list the current projects as well as select the project.
|
Couple notes:
|
||||||
To do this, we need a way to generate a string of the perspectives in alphabetical order:
|
- Function, =tab-bar-switch-to-tab=, switches or /creates/ a tab. We will always use this.
|
||||||
|
- We can switch to a tab by number with =tab-bar-select-tab=
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(setq tab-bar-show 1 ; hide bar if <= 1 tabs open
|
||||||
|
tab-bar-close-button-show nil ; hide tab close / X button
|
||||||
|
tab-bar-new-tab-choice "*dashboard*" ; buffer to show in new tabs
|
||||||
|
tab-bar-tab-hints t ; show tab numbers
|
||||||
|
|
||||||
|
;; Jump to a tab by numbers (see the keybindings set later):
|
||||||
|
tab-bar-select-tab-modifiers '(super control))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
I’ve struggled to /programmatically/ create sane workspaces, so let’s just save them off:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(desktop-save-mode 1)
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
New workspace is a tab with a specific name that opens up a specific buffer or application. My motive for such a complicated function allows me to pre-create tabs with already running applications or files.
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(defun ha--persp-label (num names)
|
(defun ha-tab-bar-new (name &optional bff)
|
||||||
"Return string of numbered elements.
|
"Create a new tab with a NAME.
|
||||||
NUM is the starting number and NAMES is a list of strings."
|
With a non-nil IFF, call IFF as a function or switch
|
||||||
(when names
|
to the IFF buffer or the files listed."
|
||||||
(concat
|
(interactive "sWorkspace Name: ")
|
||||||
(format " %d: %s%s" ; Shame that the following doesn't work:
|
(tab-bar-switch-to-tab name)
|
||||||
num ; (propertize (number-to-string num) :foreground "#00a0")
|
(when bff
|
||||||
(car names) ; Nor does surrounding the number with underbars.
|
|
||||||
|
|
||||||
(if (equal (car names) (persp-name (persp-curr))) "*" ""))
|
|
||||||
(ha--persp-label (1+ num) (cdr names)))))
|
|
||||||
|
|
||||||
(defun ha-persp-labels ()
|
|
||||||
"Return a string of numbered elements from a list of names."
|
|
||||||
(ha--persp-label 1 (sort (hash-table-keys (perspectives-hash)) 's-less?)))
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
Build the hydra as well as configure the =perspective= project.
|
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
|
||||||
(use-package perspective
|
|
||||||
:custom
|
|
||||||
(persp-modestring-short t)
|
|
||||||
(persp-show-modestring t)
|
|
||||||
|
|
||||||
:config
|
|
||||||
(setq persp-suppress-no-prefix-key-warning t)
|
|
||||||
|
|
||||||
(persp-mode)
|
|
||||||
|
|
||||||
(defhydra hydra-workspace-leader (:color blue :hint nil) "
|
|
||||||
Workspaces- %s(ha-persp-labels)
|
|
||||||
_n_: new project _r_: rename _a_: add buffer _l_: load worksp
|
|
||||||
_]_: next worksp _d_: delete _b_: goto buffer _s_: save worksp
|
|
||||||
_[_: previous _W_: init all _k_: remove buffer _`_: to last worksp "
|
|
||||||
("TAB" persp-switch-quick)
|
|
||||||
("RET" persp-switch)
|
|
||||||
("`" persp-switch-last)
|
|
||||||
("1" (persp-switch-by-number 1))
|
|
||||||
("2" (persp-switch-by-number 2))
|
|
||||||
("3" (persp-switch-by-number 3))
|
|
||||||
("4" (persp-switch-by-number 4))
|
|
||||||
("5" (persp-switch-by-number 5))
|
|
||||||
("6" (persp-switch-by-number 6))
|
|
||||||
("7" (persp-switch-by-number 7))
|
|
||||||
("8" (persp-switch-by-number 8))
|
|
||||||
("9" (persp-switch-by-number 9))
|
|
||||||
("0" (persp-switch-by-number 0))
|
|
||||||
("n" ha-project-persp)
|
|
||||||
("N" persp-switch)
|
|
||||||
("]" persp-next :color pink)
|
|
||||||
("[" persp-prev :color pink)
|
|
||||||
("d" persp-kill)
|
|
||||||
("W" ha-workspace-initialize)
|
|
||||||
("a" persp-add-buffer)
|
|
||||||
("b" persp-switch-to-buffer)
|
|
||||||
("k" persp-remove-buffer)
|
|
||||||
("K" persp-kill-buffer)
|
|
||||||
("m" persp-merge)
|
|
||||||
("u" persp-unmerge)
|
|
||||||
("i" persp-import)
|
|
||||||
("r" persp-rename)
|
|
||||||
("s" persp-state-save)
|
|
||||||
("l" persp-state-load)
|
|
||||||
("w" ha-switch-to-special) ; The most special perspective
|
|
||||||
("q" nil)
|
|
||||||
("C-g" nil)))
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
Let’s give it a binding:
|
|
||||||
#+begin_src emacs-lisp
|
|
||||||
(ha-leader "TAB" '("workspaces" . hydra-workspace-leader/body))
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
When called, it /can/ look like:
|
|
||||||
|
|
||||||
[[file:screenshots/projects-hydra.png]]
|
|
||||||
|
|
||||||
The /special/ perspective is a nice shortcut to the one I use the most:
|
|
||||||
#+begin_src emacs-lisp
|
|
||||||
(defun ha-switch-to-special ()
|
|
||||||
"Change to the projects perspective."
|
|
||||||
(interactive)
|
|
||||||
(persp-switch "projects"))
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
I often want a workspace dedicated to an /application/, so this function:
|
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
|
||||||
(defun ha-app-perspective (name func)
|
|
||||||
"Generate new perspective NAME, automatically running FUNC."
|
|
||||||
(lambda ()
|
|
||||||
(interactive)
|
|
||||||
(let ((already-started? (seq-contains-p (persp-names) name 'equal)))
|
|
||||||
(persp-switch name)
|
|
||||||
(unless already-started?
|
|
||||||
(call-interactively func)))))
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
And I can then use it like:
|
|
||||||
#+begin_src emacs-lisp :tangle no
|
|
||||||
(ha-leader "a x" `("to foobar" . ,(ha-app-perspective "foobar" #'foobar)))
|
|
||||||
#+end_src
|
|
||||||
*** Predefined Workspaces
|
|
||||||
Let's describe a list of startup project workspaces. This way, I don't need the clutter of the recent state, but also get back to a state of mental normality.
|
|
||||||
Granted, this list is essentially a list of projects that I'm currently developing, so I expect this to change often.
|
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
|
||||||
(defvar ha-workspace-projects-personal nil "List of default projects with a name.")
|
|
||||||
|
|
||||||
(add-to-list 'ha-workspace-projects-personal
|
|
||||||
'("projects" "~/projects" ("breathe.org" "tasks.org")))
|
|
||||||
(add-to-list 'ha-workspace-projects-personal
|
|
||||||
'("personal" "~/personal" ("general.org")))
|
|
||||||
(add-to-list 'ha-workspace-projects-personal
|
|
||||||
'("technical" "~/technical" ("ansible.org")))
|
|
||||||
(add-to-list 'ha-workspace-projects-personal
|
|
||||||
'("hamacs" "~/src/hamacs" ("README.org" "ha-config.org")))
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
Given a list of information about project-workspaces, can we create them all?
|
|
||||||
#+begin_src emacs-lisp
|
|
||||||
(defun ha-persp-exists? (name)
|
|
||||||
"Return non-nill if a perspective of NAME exists."
|
|
||||||
(when (fboundp 'perspectives-hash)
|
|
||||||
(seq-contains (hash-table-keys (perspectives-hash)) name)))
|
|
||||||
|
|
||||||
(defun ha-workspace-initialize (&optional projects)
|
|
||||||
"Precreate workspace projects from a PROJECTS list.
|
|
||||||
Each entry in the list is a list containing:
|
|
||||||
- name (as a string)
|
|
||||||
- project root directory
|
|
||||||
- a optional list of files to display"
|
|
||||||
(interactive)
|
|
||||||
(unless projects
|
|
||||||
(setq projects ha-workspace-projects-personal))
|
|
||||||
|
|
||||||
(dolist (project projects)
|
|
||||||
(seq-let (name root files) project
|
|
||||||
(unless (ha-persp-exists? name)
|
|
||||||
(message "Creating workspace: %s (from %s)" name root)
|
|
||||||
(ha-project-persp root name files))))
|
|
||||||
(persp-switch "main"))
|
|
||||||
#+end_src
|
|
||||||
|
|
||||||
Often, but not always, I want a perspective based on an actual Git repository, e.g. a project. Emacs calls these transients.
|
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
|
||||||
(defun ha-project-persp (project &optional name files)
|
|
||||||
"Create a new perspective, and then switch to the PROJECT.
|
|
||||||
If NAME is not given, then figure it out based on the name of the
|
|
||||||
PROJECT. If FILES aren't specified, then see if there is a
|
|
||||||
README. Otherwise, pull up Dired."
|
|
||||||
(interactive (list (completing-read "Project: "
|
|
||||||
(project-known-project-roots))))
|
|
||||||
(when (f-directory-p project)
|
|
||||||
(unless name
|
|
||||||
(setq name (f-filename project)))
|
|
||||||
(persp-switch name)
|
|
||||||
|
|
||||||
(let ((recent-files (thread-last recentf-list
|
|
||||||
(--filter (s-starts-with? project it))
|
|
||||||
(-take 3)))
|
|
||||||
(readme-org (f-join project "README.org"))
|
|
||||||
(readme-md (f-join project "README.md"))
|
|
||||||
(readme-rst (f-join project "README.rst")))
|
|
||||||
(cond
|
(cond
|
||||||
(files (ha--project-show-files project files))
|
((listp bff) (find-file (car bff))
|
||||||
(recent-files (ha--project-show-files project recent-files))
|
(dolist (f (cdr bff))
|
||||||
((f-exists? readme-org) (find-file readme-org))
|
(split-window-right)
|
||||||
((f-exists? readme-md) (find-file readme-md))
|
(find-file f)))
|
||||||
((f-exists? readme-rst) (find-file readme-rst))
|
((fboundp bff) (call-interactively bff))
|
||||||
(t (dired project))))))
|
((bufferp bff) (switch-to-buffer bff)))))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
When starting a new perspective, and I specify more than one file, this function splits the window horizontally for each file.
|
With a new tab group for a directory or probably a project, let’s see if we can load the most useful files.
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(defun ha--project-show-files (root files)
|
(defun ha-tab-bar-new-default ()
|
||||||
"Display a list of FILES in a project ROOT directory.
|
"Given a new perspective, display some buffer windows.
|
||||||
Each file gets its own window (so don't make the list of files
|
The choice of files to display depends on a combination of READMEs and
|
||||||
long)."
|
most recently viewed files in the project. This function assumes the
|
||||||
(when files
|
variable `default-directory' contains the root of the project."
|
||||||
(let ((default-directory root)
|
(cl-flet ((one-win (file) (find-file file))
|
||||||
(file (car files))
|
(two-win (left right)
|
||||||
(more (cdr files)))
|
(find-file right)
|
||||||
(message "Loading files from %s ... %s and %s" root file more)
|
(split-window-right)
|
||||||
(when (f-exists? file)
|
(find-file left))
|
||||||
(find-file file))
|
(in-project (file)
|
||||||
(when more
|
(string-match (rx bos (literal default-directory))
|
||||||
(split-window-horizontally)
|
(expand-file-name file))))
|
||||||
(ha--project-show-files root more)))))
|
(let* ((recent-files (seq-filter #'in-project recentf-list))
|
||||||
|
(recent (car recent-files))
|
||||||
|
(readme-org (expand-file-name "README.org"))
|
||||||
|
(readme-md (expand-file-name "README.md")))
|
||||||
|
(cond
|
||||||
|
;; ORG + recent
|
||||||
|
((and (file-exists-p recent) (file-exists-p readme-org))
|
||||||
|
(two-win readme-org recent))
|
||||||
|
;; MD + recent
|
||||||
|
((and (file-exists-p recent) (file-exists-p readme-md))
|
||||||
|
(two-win readme-md recent))
|
||||||
|
;; recent-only
|
||||||
|
((file-exists-p recent)
|
||||||
|
(one-win recent))
|
||||||
|
;; ORG only
|
||||||
|
((file-exists-p readme-org)
|
||||||
|
(one-win readme-org))
|
||||||
|
;; MD only
|
||||||
|
((file-exists-p readme-md)
|
||||||
|
(one-win readme-md))))))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
Create a new tab associated with a project:
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(defun ha-tab-bar-new-project (project-dir)
|
||||||
|
"Create a new tab/workspace based on a project.
|
||||||
|
The project is defined by the PROJECT-DIR directory."
|
||||||
|
(interactive (list (completing-read "Project: " (project-known-project-roots))))
|
||||||
|
(let ((name (project-name (project-current nil project-dir)))
|
||||||
|
(default-directory project-dir))
|
||||||
|
(ha-tab-bar-new name)
|
||||||
|
(project-switch-project project-dir)
|
||||||
|
(ha-tab-bar-new-default)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
If we close a tab that is a project, we want to close all the buffers associated with it. I wouldn’t do this if it wasn’t so easy to re-create them:
|
||||||
|
|
||||||
|
#+begin_src emacs-lisp
|
||||||
|
(defun ha-tab-bar-delete (tab-name)
|
||||||
|
"Delete a tab, TAB-NAME, and all buffers associated with it."
|
||||||
|
(interactive
|
||||||
|
(list (completing-read "Close tab by name: "
|
||||||
|
(mapcar (lambda (tab)
|
||||||
|
(alist-get 'name tab))
|
||||||
|
(funcall tab-bar-tabs-function)))))
|
||||||
|
(dolist (buf (ha-tab-bar-buffers tab-name))
|
||||||
|
(kill-buffer buf))
|
||||||
|
(tab-bar-close-tab-by-name tab-name))
|
||||||
|
|
||||||
|
(defun ha-tab-bar-buffers (tab-name)
|
||||||
|
"Return list of buffers associated with TAB-NAME."
|
||||||
|
(seq-filter (lambda (b)
|
||||||
|
(thread-last b
|
||||||
|
(tab-bar-get-buffer-tab)
|
||||||
|
(alist-get 'name)
|
||||||
|
(string-equal tab-name)))
|
||||||
|
(buffer-list)))
|
||||||
|
#+end_src
|
||||||
|
|
||||||
|
And some shortcut keys from the =general= project:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(general-nmap :prefix "SPC"
|
||||||
|
"<tab>" '(:ignore t :which-key "workspaces")
|
||||||
|
"<tab> <tab>" '("switch" . tab-switch)
|
||||||
|
"<tab> p" '("new project" . ha-tab-bar-new-project)
|
||||||
|
"<tab> n" '("new space" . ha-tab-bar-new)
|
||||||
|
"<tab> d" '("delete space" . ha-tab-bar-delete))
|
||||||
|
|
||||||
|
(global-set-key (kbd "s-C-t") 'ha-tab-bar-new)
|
||||||
|
(global-set-key (kbd "s-C-[") 'tab-bar-switch-to-prev-tab)
|
||||||
|
(global-set-key (kbd "s-C-]") 'tab-bar-switch-to-next-tab)
|
||||||
|
|
||||||
|
(tab-bar-mode 1)
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
I want to quickly jump, by the number shown on the tab, to that grouping. The following two functions create leader sequences with the name of the tab group:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(defun ha-tab-update-names ()
|
||||||
|
"Create normal-mode keybindings for the tab groupings.
|
||||||
|
This creates `SPC TAB 1' to jump to the first tab, etc."
|
||||||
|
;; Remove all previously created keybindings:
|
||||||
|
(ignore-errors
|
||||||
|
(dolist (indx (number-sequence 1 9))
|
||||||
|
(general-nmap :prefix "SPC" (format "<tab> %d" indx) nil)))
|
||||||
|
|
||||||
|
;; Loop through the existing tabs, create keys for each:
|
||||||
|
(seq-do-indexed 'ha-tab-update-tab-keybinding (tab-bar-tabs)))
|
||||||
|
|
||||||
|
(defun ha-tab-update-tab-keybinding (tab-deets indx)
|
||||||
|
"Create a keybinding to jump to tab described by TAB-DEETS.
|
||||||
|
The key sequence, `SPC' `TAB' then INDX."
|
||||||
|
(let ((name (alist-get 'name tab-deets)))
|
||||||
|
(general-nmap :prefix "SPC"
|
||||||
|
(format "<tab> %d" (1+ indx))
|
||||||
|
`(,name .
|
||||||
|
(lambda () (interactive) (tab-bar-select-tab ,(1+ indx)))))))
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
|
Any time I create or delete a new tab, we can call =ha-tab-update-names=:
|
||||||
|
|
||||||
|
#+BEGIN_SRC emacs-lisp
|
||||||
|
(advice-add #'tab-bar-new-tab :after #'ha-tab-update-names)
|
||||||
|
(advice-add #'tab-bar-close-tab :after #'ha-tab-update-names)
|
||||||
|
(advice-add #'tab-bar-close-other-tabs :after #'ha-tab-update-names)
|
||||||
|
|
||||||
|
(add-hook desktop-after-read-hook #'ha-tab-update-names)
|
||||||
|
#+END_SRC
|
||||||
|
|
||||||
* Pretty Good Encryption
|
* Pretty Good Encryption
|
||||||
For details on using GnuPG in Emacs, see Mickey Petersen’s [[https://www.masteringemacs.org/article/keeping-secrets-in-emacs-gnupg-auth-sources][GnuPG Essay]].
|
For details on using GnuPG in Emacs, see Mickey Petersen’s [[https://www.masteringemacs.org/article/keeping-secrets-in-emacs-gnupg-auth-sources][GnuPG Essay]].
|
||||||
|
|
||||||
|
|
|
@ -169,12 +169,11 @@ The [[https://github.com/emacs-dashboard/emacs-dashboard][emacs-dashboard]] proj
|
||||||
dashboard-set-heading-icons t
|
dashboard-set-heading-icons t
|
||||||
dashboard-footer-messages (list (ha--dad-joke)))
|
dashboard-footer-messages (list (ha--dad-joke)))
|
||||||
|
|
||||||
:config
|
|
||||||
(dashboard-setup-startup-hook)
|
|
||||||
|
|
||||||
;; Real shame that :config is incompatible with :hook, otherwise:
|
;; Real shame that :config is incompatible with :hook, otherwise:
|
||||||
;; :hook (dashboard-after-initialize . ha-dashboard)
|
;; :hook (dashboard-after-initialize . ha-dashboard)
|
||||||
(add-hook 'dashboard-after-initialize-hook 'ha-dashboard))
|
|
||||||
|
:config
|
||||||
|
(dashboard-setup-startup-hook))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
This dashboard project requires [[https://github.com/purcell/page-break-lines][page-break-lines]] (which is a nice project):
|
This dashboard project requires [[https://github.com/purcell/page-break-lines][page-break-lines]] (which is a nice project):
|
||||||
|
@ -264,6 +263,7 @@ The =dashboard= project hooks to [[help:emacs-startup-hook][emacs-startup-hook]]
|
||||||
(defun ha-dashboard ()
|
(defun ha-dashboard ()
|
||||||
"Shows the extra stuff with the dashboard."
|
"Shows the extra stuff with the dashboard."
|
||||||
(interactive)
|
(interactive)
|
||||||
|
(tab-bar-switch-to-tab "main")
|
||||||
(switch-to-buffer "*dashboard*")
|
(switch-to-buffer "*dashboard*")
|
||||||
(setq-local mode-line-format nil)
|
(setq-local mode-line-format nil)
|
||||||
(delete-other-windows)
|
(delete-other-windows)
|
||||||
|
|
|
@ -63,14 +63,9 @@ To make the active window /more noticeable/, we /dim/ the in-active windows with
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(use-package dimmer
|
(use-package dimmer
|
||||||
:custom (dimmer-adjustment-mode :foreground))
|
:custom (dimmer-adjustment-mode :foreground)
|
||||||
#+end_src
|
|
||||||
|
|
||||||
I get issues with Magic and Dimmer, so let’s turn off this feature in certain windows:
|
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
|
||||||
(use-package dimmer
|
|
||||||
:config
|
:config
|
||||||
|
;; I get issues with Magit and Dimmer, so let’s turn off this feature in certain windows:
|
||||||
(dimmer-configure-which-key) ; Do not dim these special windows
|
(dimmer-configure-which-key) ; Do not dim these special windows
|
||||||
(dimmer-configure-hydra)
|
(dimmer-configure-hydra)
|
||||||
(dimmer-configure-magit)
|
(dimmer-configure-magit)
|
||||||
|
@ -89,6 +84,7 @@ either be "there or not" which resulted large jumps and large distractions.
|
||||||
:straight (:type git :host github :repo "jdtsmith/ultra-scroll")
|
:straight (:type git :host github :repo "jdtsmith/ultra-scroll")
|
||||||
:config
|
:config
|
||||||
(setq scroll-conservatively 101 ; important!
|
(setq scroll-conservatively 101 ; important!
|
||||||
|
pixel-scroll-precision-interpolate-page t
|
||||||
scroll-margin 0)
|
scroll-margin 0)
|
||||||
(ultra-scroll-mode 1))
|
(ultra-scroll-mode 1))
|
||||||
#+END_SRC
|
#+END_SRC
|
||||||
|
@ -661,7 +657,9 @@ Suggests to bind some keys to =hl-todo-next= in order to jump from tag to tag, b
|
||||||
(?f . "FIXME")
|
(?f . "FIXME")
|
||||||
(?n . "NOTE"))
|
(?n . "NOTE"))
|
||||||
"Mapping of narrow and keywords.")
|
"Mapping of narrow and keywords.")
|
||||||
:general (:states 'normal "g t" '("jump todos" . consult-todo)))
|
;; :config
|
||||||
|
;; (evil-define-key '(normal) 'global "g t" '("jump todos" . consult-todo))
|
||||||
|
)
|
||||||
#+end_src
|
#+end_src
|
||||||
* Full Size Frame
|
* Full Size Frame
|
||||||
Taken from [[https://emacsredux.com/blog/2020/12/04/maximize-the-emacs-frame-on-startup/][this essay]], I figured I would start the initial frame automatically in fullscreen, but not any subsequent frames (as this could be part of the capturing system).
|
Taken from [[https://emacsredux.com/blog/2020/12/04/maximize-the-emacs-frame-on-startup/][this essay]], I figured I would start the initial frame automatically in fullscreen, but not any subsequent frames (as this could be part of the capturing system).
|
||||||
|
|
|
@ -133,7 +133,7 @@ Also, let's do some basic configuration of Emacs' mail system:
|
||||||
|
|
||||||
Create a special mail perspective:
|
Create a special mail perspective:
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(ha-leader "a M" `("mail" . ,(ha-app-perspective "mail" #'notmuch)))
|
(ha-leader "a M" `("mail" . ,(ha-tab-bar-new "mail" #'notmuch)))
|
||||||
#+end_src
|
#+end_src
|
||||||
* Configuration
|
* Configuration
|
||||||
Do I want to sign messages by default? Nope.
|
Do I want to sign messages by default? Nope.
|
||||||
|
|
|
@ -87,7 +87,7 @@ According to Ben Maughan and [[http://pragmaticemacs.com/emacs/to-eww-or-not-to-
|
||||||
|
|
||||||
And some global keys to display them in the =apps= menu:
|
And some global keys to display them in the =apps= menu:
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(ha-leader "a f" `("feed reader" . ,(ha-app-perspective "elfeed" #'elfeed)))
|
(ha-leader "a f" `("feed reader" . ,(ha-tab-bar-new "elfeed" #'elfeed)))
|
||||||
#+end_src
|
#+end_src
|
||||||
* The Feeds :elfeed:
|
* The Feeds :elfeed:
|
||||||
The [[https://github.com/remyhonig/elfeed-org][elfeed-org]] project configures =elfeed= to read the RSS feeds from an Org file … like this one!
|
The [[https://github.com/remyhonig/elfeed-org][elfeed-org]] project configures =elfeed= to read the RSS feeds from an Org file … like this one!
|
||||||
|
|
|
@ -521,6 +521,7 @@ The goal here is toggle switches and other miscellaneous settings.
|
||||||
"t T" '("tramp mode" . tramp-mode)
|
"t T" '("tramp mode" . tramp-mode)
|
||||||
"t v" '("visual" . visual-line-mode)
|
"t v" '("visual" . visual-line-mode)
|
||||||
"t w" '("whitespace" . whitespace-mode)
|
"t w" '("whitespace" . whitespace-mode)
|
||||||
|
"t <tab>" '("tab-bar" . tab-bar-mode)
|
||||||
|
|
||||||
"t <escape>" '(keyboard-escape-quit :which-key t)
|
"t <escape>" '(keyboard-escape-quit :which-key t)
|
||||||
"t C-g" '(keyboard-escape-quit :which-key t))
|
"t C-g" '(keyboard-escape-quit :which-key t))
|
||||||
|
@ -546,13 +547,10 @@ And put it on the toggle menu:
|
||||||
(ha-leader "t n" '("narrow" . ha-narrow-dwim))
|
(ha-leader "t n" '("narrow" . ha-narrow-dwim))
|
||||||
#+end_src
|
#+end_src
|
||||||
* Window Operations
|
* Window Operations
|
||||||
While it comes with Emacs, I use [[https://www.emacswiki.org/emacs/WinnerMode][winner-mode]] to undo window-related changes:
|
While it comes with Emacs, the =tab-bar= feature keeps track of all window configurations within a tab, allowing me to revert situations where I accidentally delete all the windows.
|
||||||
|
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(use-package winner
|
(tab-bar-history-mode)
|
||||||
:custom
|
|
||||||
(winner-dont-bind-my-keys t)
|
|
||||||
:config
|
|
||||||
(winner-mode +1))
|
|
||||||
#+end_src
|
#+end_src
|
||||||
** Ace Window
|
** Ace Window
|
||||||
Use the [[https://github.com/abo-abo/ace-window][ace-window]] project to jump to any window you see.
|
Use the [[https://github.com/abo-abo/ace-window][ace-window]] project to jump to any window you see.
|
||||||
|
|
|
@ -102,7 +102,7 @@ Quick way to start and jump to my IRC world.
|
||||||
|
|
||||||
And some global keys to display them:
|
And some global keys to display them:
|
||||||
#+begin_src emacs-lisp
|
#+begin_src emacs-lisp
|
||||||
(ha-leader "a i" `("irc" . ,(ha-app-perspective "irc" #'ha-erc)))
|
(ha-leader "a i" `("irc" . ,(ha-tab-bar-new "irc" #'ha-erc)))
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
And a quick shortcuts to call it:
|
And a quick shortcuts to call it:
|
||||||
|
|
|
@ -323,8 +323,6 @@ Let’s make a /theme/:
|
||||||
'hamacs
|
'hamacs
|
||||||
`(default ((t (:foreground ,default-fg :background ,default-bg))))
|
`(default ((t (:foreground ,default-fg :background ,default-bg))))
|
||||||
`(fringe ((t :background ,default-bg)))
|
`(fringe ((t :background ,default-bg)))
|
||||||
`(tab-bar ((t :foreground ,default-fg :background ,default-bg)))
|
|
||||||
`(tab-line ((t :foreground ,default-fg :background ,default-bg)))
|
|
||||||
`(window-divider ((t :foreground "black")))
|
`(window-divider ((t :foreground "black")))
|
||||||
`(cursor ((t (:foreground ,gray-10 :background ,cursor))))
|
`(cursor ((t (:foreground ,gray-10 :background ,cursor))))
|
||||||
`(region ((t (:background ,region))))
|
`(region ((t (:background ,region))))
|
||||||
|
@ -333,6 +331,11 @@ Let’s make a /theme/:
|
||||||
`(mode-line-active ((t (:background ,active))))
|
`(mode-line-active ((t (:background ,active))))
|
||||||
`(mode-line-inactive ((t (:background ,inactive))))
|
`(mode-line-inactive ((t (:background ,inactive))))
|
||||||
|
|
||||||
|
`(tab-bar ((t :foreground ,default-fg :background ,default-bg)))
|
||||||
|
`(tab-line ((t :foreground ,default-fg :background ,default-bg)))
|
||||||
|
`(tab-bar-tab ((t (:inherit variable-pitch :background ,active))))
|
||||||
|
`(tab-bar-tab-inactive ((t (:inherit variable-pitch :background ,inactive))))
|
||||||
|
|
||||||
`(doom-modeline-buffer-path ((t (:foreground ,almond))))
|
`(doom-modeline-buffer-path ((t (:foreground ,almond))))
|
||||||
`(doom-modeline-buffer-file ((t (:foreground "white" :weight bold))))
|
`(doom-modeline-buffer-file ((t (:foreground "white" :weight bold))))
|
||||||
`(doom-modeline-buffer-major-mode ((t (:foreground ,almond))))
|
`(doom-modeline-buffer-major-mode ((t (:foreground ,almond))))
|
||||||
|
|
Loading…
Reference in a new issue