diff --git a/bin/org-capture b/bin/org-capture index 7f2998481..507b02faa 100755 --- a/bin/org-capture +++ b/bin/org-capture @@ -33,7 +33,7 @@ shift $((OPTIND-1)) if [[ $daemon ]]; then emacsclient -a "" \ - -c -F '((name . "org-capture") (width . 70) (height . 25))' \ + -c -F '((name . "org-capture") (width . 70) (height . 25) (transient . t))' \ -e "(+org-capture/open-frame \"$str\" ${key:-nil})" else # Non-daemon servers flicker a lot if frames are created from terminal, so diff --git a/core/core-projects.el b/core/core-projects.el index 75b7ff91a..3f2bec85c 100644 --- a/core/core-projects.el +++ b/core/core-projects.el @@ -68,16 +68,23 @@ you want to interactive with a project other than the one you're in." (remhash (format "%s-%s" fn default-directory) projectile-project-root-cache))) (defun doom-project-p (&optional nocache) - "Whether or not this buffer is currently in a project or not." + "Return t if this buffer is currently in a project. +If NOCACHE, don't fetch a cached answer." (if nocache (without-project-cache! (doom-project-p nil)) (let ((projectile-require-project-root t)) - (projectile-project-p)))) + (and (projectile-project-p) t)))) + +(defun doom-project-name (&optional nocache) + "Return the name of the current project. +If NOCACHE, don't fetch a cached answer." + (if nocache + (without-project-cache! (doom-project-name nil)) + (projectile-project-name))) (defun doom-project-root (&optional nocache) - "Get the path to the root of your project. -If STRICT-P, return nil if no project was found, otherwise return -`default-directory'." + "Returns the root of your project, or `default-directory' if none was found. +If NOCACHE, don't fetch a cached answer." (if nocache (without-project-cache! (doom-project-root nil)) (let (projectile-require-project-root) diff --git a/modules/completion/ivy/config.el b/modules/completion/ivy/config.el index e592cb37a..2c439a53a 100644 --- a/modules/completion/ivy/config.el +++ b/modules/completion/ivy/config.el @@ -80,7 +80,7 @@ immediately runs it on the current candidate (ending the ivy session)." counsel-describe-face counsel-M-x counsel-file-jump counsel-find-file counsel-find-library counsel-info-lookup-symbol counsel-imenu counsel-recentf counsel-yank-pop - counsel-descbinds) + counsel-descbinds counsel-org-capture) :init (map! [remap apropos] #'counsel-apropos [remap bookmark-jump] #'counsel-bookmark diff --git a/modules/feature/popup/autoload.el b/modules/feature/popup/autoload.el index e2d999a44..2f116c535 100644 --- a/modules/feature/popup/autoload.el +++ b/modules/feature/popup/autoload.el @@ -525,7 +525,7 @@ Accepts the same arguments as `display-buffer-in-side-window'. You must set ((not (numberp slot)) (error "Invalid slot %s specified" slot)) ((not (numberp vslot)) - (error "Invalid vslot %s specified" slot))) + (error "Invalid vslot %s specified" vslot))) (let* ((major (get-window-with-predicate (lambda (window) diff --git a/modules/feature/version-control/+git.el b/modules/feature/version-control/+git.el index 244047b10..d8e3b6504 100644 --- a/modules/feature/version-control/+git.el +++ b/modules/feature/version-control/+git.el @@ -69,9 +69,8 @@ ;; Sometimes I forget `git-timemachine' is enabled in a buffer, so instead of ;; showing revision details in the minibuffer, show them in ;; `header-line-format', which has better visibility. - (setq git-timemachine-show-minibuffer-details nil) - (add-hook 'git-timemachine-mode-hook #'+vcs|init-header-line) - (advice-add #'git-timemachine-show-revision :after #'+vcs*update-header-line) + (setq git-timemachine-show-minibuffer-details t) + (advice-add #'git-timemachine--show-minibuffer-details :override #'+vcs*update-header-line) ;; Force evil to rehash keybindings for the current state (add-hook 'git-timemachine-mode-hook #'evil-force-normal-state)) diff --git a/modules/feature/version-control/autoload.el b/modules/feature/version-control/autoload.el index 6df86c3d0..e3f9a4cf4 100644 --- a/modules/feature/version-control/autoload.el +++ b/modules/feature/version-control/autoload.el @@ -32,12 +32,20 @@ repository root." (user-error "No git root found!"))) ;;;###autoload -(defun +vcs|init-header-line () - "Toggle the git-timemachine header-line on activate. Use this on -`git-timemachine-mode-hook'." - (if git-timemachine-mode - (+vcs*update-header-line) - (setq-local header-line-format nil))) +(defun +vcs*update-header-line (revision) + "Show revision details in the header-line, instead of the minibuffer. + +Sometimes I forget `git-timemachine' is enabled in a buffer. Putting revision +info in the `header-line-format' is a good indication." + (let* ((date-relative (nth 3 revision)) + (date-full (nth 4 revision)) + (author (if git-timemachine-show-author (concat (nth 6 revision) ": ") "")) + (sha-or-subject (if (eq git-timemachine-minibuffer-detail 'commit) (car revision) (nth 5 revision)))) + (setq header-line-format + (format "%s%s [%s (%s)]" + (propertize author 'face 'git-timemachine-minibuffer-author-face) + (propertize sha-or-subject 'face 'git-timemachine-minibuffer-detail-face) + date-full date-relative)))) ;;;###autoload (defun +vcs|enable-smerge-mode-maybe () @@ -49,22 +57,3 @@ repository root." (when (and (featurep 'hydra) +vcs-auto-hydra-smerge) (+hydra-smerge/body))))) - -;;;###autoload -(defun +vcs*update-header-line (&rest _) - "Show revision details in the header-line, instead of the minibuffer. - -Sometimes I forget `git-timemachine' is enabled in a buffer. Putting info into, -putting them in `header-line-format' has better visibility." - (when (and git-timemachine-mode git-timemachine-revision) - (let* ((revision git-timemachine-revision) - (date-relative (nth 3 revision)) - (date-full (nth 4 revision)) - (author (if git-timemachine-show-author (concat (nth 6 revision) ": ") "")) - (sha-or-subject (if (eq git-timemachine-minibuffer-detail 'commit) (car revision) (nth 5 revision)))) - (setq-local - header-line-format - (format "%s%s [%s (%s)]" - (propertize author 'face 'git-timemachine-minibuffer-author-face) - (propertize sha-or-subject 'face 'git-timemachine-minibuffer-detail-face) - date-full date-relative))))) diff --git a/modules/feature/workspaces/autoload/workspaces.el b/modules/feature/workspaces/autoload/workspaces.el index 1b6ee329a..8d71d4f2f 100644 --- a/modules/feature/workspaces/autoload/workspaces.el +++ b/modules/feature/workspaces/autoload/workspaces.el @@ -490,28 +490,33 @@ created." ;;;###autoload (defun +workspaces|switch-to-project (&optional inhibit-prompt) "Creates a workspace dedicated to a new project. If one already exists, switch -to it. Should be hooked to `projectile-after-switch-project-hook'." +to it. If in the main workspace and it's empty, recycle that workspace, without +renaming it. + +Should be hooked to `projectile-after-switch-project-hook'." (when (and persp-mode +workspaces--project-dir) (unwind-protect - (let (persp-p) - (let* ((persp - (let* ((default-directory +workspaces--project-dir) - projectile-project-name - projectile-require-project-root - projectile-cached-buffer-file-name - projectile-cached-project-root - (project-name (projectile-project-name))) - (or (setq persp-p (+workspace-get project-name t)) - (+workspace-new project-name)))) - (new-name (persp-name persp))) - (+workspace-switch new-name) - (unless persp-p - (switch-to-buffer (doom-fallback-buffer))) - (unless inhibit-prompt - (doom-project-find-file +workspaces--project-dir)) - (+workspace-message - (format "Switched to '%s' in new workspace" new-name) - 'success))) + (if (+workspace-buffer-list) + (let (persp-p) + (let* ((persp + (let* ((default-directory +workspaces--project-dir) + (project-name (doom-project-name 'nocache))) + (or (setq persp-p (+workspace-get project-name t)) + (+workspace-new project-name)))) + (new-name (persp-name persp))) + (+workspace-switch new-name) + (unless persp-p + (switch-to-buffer (doom-fallback-buffer))) + (unless inhibit-prompt + (doom-project-find-file +workspaces--project-dir)) + (+workspace-message + (format "Switched to '%s' in new workspace" new-name) + 'success))) + (with-current-buffer (switch-to-buffer (doom-fallback-buffer)) + (setq default-directory +workspaces--project-dir) + (message "Switched to '%s'" (doom-project-name 'nocache))) + (unless inhibit-prompt + (doom-project-find-file +workspaces--project-dir))) (setq +workspaces--project-dir nil)))) diff --git a/modules/lang/org/autoload/org-capture.el b/modules/lang/org/autoload/org-capture.el index bd7dce4d4..6edabe44e 100644 --- a/modules/lang/org/autoload/org-capture.el +++ b/modules/lang/org/autoload/org-capture.el @@ -34,6 +34,7 @@ Uses the capture template specified by KEY. Otherwise, prompts you for one." `((name . "org-capture") (width . 70) (height . 25) + (transient . t) (window-system . ,(cond (IS-MAC 'ns) (IS-LINUX 'x) (t 'w32))) @@ -50,31 +51,46 @@ Uses the capture template specified by KEY. Otherwise, prompts you for one." (defun +org-capture-frame-p (&rest _) "Return t if the current frame is an org-capture frame opened by `+org-capture/open-frame'." - (equal "org-capture" (frame-parameter nil 'name))) + (and (equal "org-capture" (frame-parameter nil 'name)) + (frame-parameter nil 'transient))) ;;;###autoload (defun +org-capture/open-frame (&optional string key) "Opens the org-capture window in a floating frame that cleans itself up once you're done. This can be called from an external shell script." (interactive) - (require 'org) - (let (after-make-frame-functions before-make-frame-hook) - (let ((frame (if (+org-capture-frame-p) - (selected-frame) - (make-frame +org-capture-window-params)))) - (with-selected-frame frame - (condition-case ex - (cl-letf (((symbol-function #'pop-to-buffer) - (symbol-function #'switch-to-buffer))) - (if (and (stringp string) - (not (string-empty-p string))) - (org-capture-string string key) - (org-capture nil key)) - (when (featurep 'solaire-mode) - (solaire-mode +1))) - ('error - (message "org-capture: %s" (error-message-string ex)) - (delete-frame frame))))))) + (when (and string (string-empty-p string)) + (setq string nil)) + (when (and key (string-empty-p key)) + (setq key nil)) + (require 'org-capture) + (let ((frame (if (+org-capture-frame-p) + (selected-frame) + (make-frame +org-capture-window-params)))) + (with-selected-frame frame + (condition-case ex + (cl-letf (((symbol-function #'pop-to-buffer) + (symbol-function #'switch-to-buffer))) + (switch-to-buffer (doom-fallback-buffer)) + (let ((org-capture-initial string) + (org-capture-mode-hook org-capture-mode-hook) + org-capture-entry) + (when (and key (not (string-empty-p key))) + (setq org-capture-entry (org-capture-select-template key))) + (if (or org-capture-entry + (not (fboundp 'counsel-org-capture))) + (org-capture) + (unwind-protect + (counsel-org-capture) + (if-let* ((buf (cl-loop for buf in (buffer-list) + if (buffer-local-value 'org-capture-mode buf) + return buf))) + (with-current-buffer buf + (add-hook 'kill-buffer-hook #'+org-capture|cleanup-frame nil t)) + (delete-frame frame)))))) + ('error + (message "org-capture: %s" (error-message-string ex)) + (delete-frame frame)))))) ;;;###autoload (defun +org-capture-available-keys () diff --git a/modules/private/default/+bindings.el b/modules/private/default/+bindings.el index cf4fd153c..d03f58a6b 100644 --- a/modules/private/default/+bindings.el +++ b/modules/private/default/+bindings.el @@ -55,7 +55,7 @@ :ne "M-b" #'+eval/build :ne "M-a" #'mark-whole-buffer :ne "M-c" #'evil-yank - :ne "M-q" (if (daemonp) #'delete-frame #'save-buffers-kill-emacs) + :ne "M-q" (if (daemonp) #'delete-frame #'evil-quit-all) :ne "M-f" #'swiper :n "M-s" #'save-buffer :m "A-j" #'+default:multi-next-line diff --git a/modules/ui/doom/config.el b/modules/ui/doom/config.el index 139328fba..045edfdb8 100644 --- a/modules/ui/doom/config.el +++ b/modules/ui/doom/config.el @@ -27,7 +27,11 @@ :config (setq solaire-mode-real-buffer-fn #'doom-real-buffer-p) ;; Prevent color glitches when reloading either DOOM or the theme - (add-hook! '(doom-init-theme-hook doom-reload-hook) #'solaire-mode-reset)) + (add-hook! '(doom-init-theme-hook doom-reload-hook) + #'solaire-mode-reset) + ;; org-capture takes an org buffer and narrows it. The result is erroneously + ;; considered an unreal buffer, so solaire-mode must be restored. + (add-hook 'org-capture-mode-hook #'turn-on-solaire-mode)) (after! hideshow