Emacs configuration and packages
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

17 KiB

Completion configuration

completion styles

  (use-package emacs
    (setq completion-category-defaults nil
          completion-cycle-threshold nil
          '((file (styles . (partial-completion))))))


  (use-package orderless
    :ensure t
    (setq completion-styles '(orderless)
          orderless-skip-highlighting nil
          orderless-component-separator "[ -/]+"
          '(orderless-literal orderless-regexp orderless-initialism)))


  (use-package corfu
    :ensure t
    :demand t
    :init (setq tab-always-indent 'complete
                corfu-echo-documentation 0.25
                corfu-cycle t
                corfu-count 15
                corfu-quit-no-match t ; setting this to nil
                corfu-auto t          ; and this to nil is another option
                corfu-commit-predicate nil            ; when nil, we set:
                orderless-component-separator "[-/]+" ; no space (it aborts)
                corfu-min-width 20
                corfu-max-width 100)
    (defun jao-corfu-enable-no-auto ()
      (setq-local corfu-auto nil)
      (corfu-mode 1))

    (defmacro jao-corfu-no-auto (mode)
      (let ((mode-name (intern (format "%s-mode" mode)))
            (hook-name (intern (format "%s-mode-hook" mode))))
        `(with-eval-after-load ',mode
           (add-to-list 'corfu-excluded-modes ',mode-name)
           (add-hook ',hook-name #'jao-corfu-enable-no-auto))))

    (jao-corfu-no-auto eshell)

    :bind (:map corfu-map
                ([remap next-line] . nil)
                ([remap previous-line] . nil)
                ([tab] . corfu-next)
                ("M-n" . corfu-next)
                ("M-p" . corfu-previous)))

  (corfu-global-mode 1)


  (use-package vertico
    :ensure t
    :init (setq vertico-count 20
                vertico-cycle t
                vertico-group-format nil
                org-refile-use-outline-path t)

    ;; (defun jao--be-orderless (&rest _any)
    ;;   (setq-local completion-styles '(orderless)))
    ;; (unless (eq completion-styles '(orderless))
    ;;   (advice-add 'vertico--setup :before #'jao--be-orderless))



  (use-package marginalia
    :ensure t
    :bind (:map minibuffer-local-map ("C-M-a" . marginalia-cycle))

    :custom ((marginalia-align-offset 1)
             (marginalia-margin-threshold 200)
             (marginalia-separator-threshold 120)
             (marginalia-truncate-width 100)
              '(marginalia-annotators-heavy marginalia-annotators-light nil))))

  (marginalia-mode 1)



  (use-package consult
    :ensure t
    :bind (("C-x M-:" . consult-complex-command)
           ("C-x b" . consult-buffer)
           ("C-x C-b" . consult-buffer)
           ("C-c b" . project-find-file)
           ("C-c B" . bookmark-set)
           ("C-c h" . consult-history)
           ("C-c i" . consult-imenu)
           ("C-c I" . consult-project-imenu)
           ("C-c k" . consult-ripgrep)
           ("C-c K" . consult-git-grep)
           ("C-c l" . consult-locate)
           ("C-c m" . consult-mode-command)
           ("C-c s" . consult-line)
           ("C-x r x" . consult-register)
           ("C-x r b" . consult-bookmark)
           ("M-g b" . consult-bookmark)
           ("M-g m" . consult-mark)
           ("M-g e" . consult-error)
           ("M-s m" . consult-multi-occur)
           ("M-s o" . consult-outline)
           ("M-y" . consult-yank-pop)
           ("C-s" . isearch-forward)
           ("C-S-s" . consult-line)
           ("<help> a" . consult-apropos))

    :custom ((consult-locate-command "locate --ignore-case --regexp ARG OPTS")
             (consult-preview-key (kbd "`")))

    (fset 'multi-occur #'consult-multi-occur)

    (require 'jao-compilation)
    (defun jao-consult-project-root ()
      (expand-file-name (or (vc-root-dir) (jao-compilation-root) "")))

    (setq consult-project-root-function #'jao-consult-project-root)

    (define-key consult-narrow-map (vconcat consult-narrow-key "?")

    (consult-customize consult-mark :preview-key 'any))


  (jao-load-path "consult-recoll")

  (defun jao-recoll-format (title url mtype)
    (let* ((u (replace-regexp-in-string "/home/jao/" "" url))
           (u (replace-regexp-in-string "\\(doc\\|org/doc\\|var/mail\\)/" "" u)))
      (format "%s (%s, %s)"
              (propertize u 'face 'jao-themes-f00)
              (propertize mtype 'face 'jao-themes-f01))))

  (use-package consult-recoll
    :init (setq consult-recoll-open-fns
                '(("application/pdf" . jao-open-doc)
                  ("message/rfc822" . jao-org-links-open-mail))
                consult-recoll-format-candidate #'jao-recoll-format)
    :bind (("C-c R" . #'consult-recoll)))

dh-diff hunks

  (defun jao-consult--diff-lines (&optional backward)
    (let ((candidates)
          (width (length (number-to-string
                          (line-number-at-pos (point-max)
        (while (ignore-errors (diff-hl-next-hunk backward))
          (let* ((str (buffer-substring (line-beginning-position)
                 (no (line-number-at-pos (point)))
                 (no (consult--line-number-prefix (point-marker) no width)))
            (push (concat no str) candidates))))
      (if backward candidates (nreverse candidates))))

  (defun jao-consult-hunks ()
    (let ((candidates (append (jao-consult--diff-lines)
                              (jao-consult--diff-lines t))))
      (unless candidates (error "No changes!"))
       (consult--read candidates
                      :prompt "Go to hunk: "
                      :category 'consult--encode-location
                      :sort nil
                      :require-match t
                      :lookup #'consult--line-match
                      :state (consult--jump-state)))))

  (with-eval-after-load "consult"
    (consult-customize '((jao-consult-hunks :preview-key any)))
    (global-set-key (kbd "C-x v c") #'jao-consult-hunks))

narrow helpers

  (defvar jao-consult-narrow nil)

  (defun jao-consult-initial-narrow ()
    (when (eq this-command #'consult-buffer)
      (when-let (c (cdr (assoc (jao-afio-current-frame) jao-consult-narrow)))
        (setq unread-command-events
              (append unread-command-events `(,c 32))))))

  (add-hook 'minibuffer-setup-hook #'jao-consult-initial-narrow)

  (defmacro jao-consult--mode-buffers (&rest modes)
    `(lambda ()
       (seq-map #'buffer-name
                (seq-filter (lambda (b)
                              (with-current-buffer b
                                (derived-mode-p ,@modes)))

  (defun jao-consult-add-buffer-source (src &optional aframe key)
    (add-to-list 'consult-buffer-sources src t)
    (when (and aframe key)
      (add-to-list 'jao-consult-narrow (cons aframe key))))

narrowing chats

  (defvar jao-chat-buffer-source
    (list :name "chats"
          :category 'buffer
          :action #'pop-to-buffer
          :hidden t
          :narrow (cons ?c "chats")
          :items (jao-consult--mode-buffers 'erc-mode
  (jao-consult-add-buffer-source 'jao-chat-buffer-source)

consult dir

  (use-package consult-dir
    :ensure t
    :bind (("C-x C-d" . consult-dir)
           :map minibuffer-local-completion-map
           (("C-x C-d" . consult-dir)
            ("C-x C-j" . consult-dir-jump-file))))



  (use-package embark
    :ensure t
    :demand t
    (setq embark-quit-after-action nil
          '(jao-embark--bindings "\n" target "  " jao-embark--other)
          embark-indicator #'embark-mixed-indicator
          embark-mixed-indicator-both nil
          '(embark-become embark-export embark-collect)
          embark-verbose-indicator-nested nil
            (window-parameters (mode-line-format . none))
            (window-height . fit-window-to-buffer)))

    (defvar jao-embark--brx
      "^\\(\\([^ ] \\)+\\|RET\\|TAB\\|SPC\\)\\( *\\)\\([^ ]+ +\\)\\(.*\\)$")

    (defun jao-embark--cmp (x y)
      (let* ((lxk (get-text-property 0 'kbd x))
             (lyk (get-text-property 0 'kbd y)))
        (if (= lxk lyk) (string< x y) (< lxk lyk))))

    (defun jao-embark--cmd-doc (cmd)
      (propertize (car (split-string (or (embark--function-doc cmd) "") "\n"))
                  'face 'embark-verbose-indicator-documentation))

    (defun jao--max-len (strs)
      (seq-reduce (lambda (m x) (max m (length x))) strs 0))

    (cl-defun jao-embark--other (&key shadowed-targets &allow-other-keys)
      (propertize (format "%s" (or shadowed-targets ""))
                  'face 'embark-verbose-indicator-shadowed))

    (cl-defun jao-embark--bindings (&key bindings &allow-other-keys)
      (let* ((cmds (mapcar #'caddr bindings))
             (docs (mapcar #'jao-embark--cmd-doc cmds))
             (keys (mapcar (lambda (b)
                             (propertize (car (last b))
                                         'face 'embark-keybinding))
             (cmds (mapcar (lambda (b)
                             (propertize (cadr b) 'face 'embark-command))
             (fmt (format "%%-%ds   %%-%ds     %%s\n"
                          (jao--max-len cmds) (jao--max-len keys)))
             (res (seq-mapn (lambda (c k d)
                              (let ((n (if (string-prefix-p "embark-" c)
                                         (length k))))
                                (propertize (format fmt c k d) 'kbd n)))
                            cmds keys docs)))
        (apply #'concat (seq-sort #'jao-embark--cmp res))))

    :bind (("C-;" . embark-act)
           ("C-'" . embark-dwim)
           (:map minibuffer-local-map
                 (("C-'" . embark-dwim)
                  ("C-," . embark-become)
                  ("C-o" . embark-export)))))

  (use-package embark-consult
    :ensure t
    :after (embark consult))

  (with-eval-after-load 'consult
    (with-eval-after-load 'embark
      (require 'embark-consult)))

org targets

  (declare-function org-link-any-re "ol")
  (declare-function org-open-link-from-string "ol")
  (declare-function org-in-regexp "org-macs")

  (defun jao-embark-targets--org-link ()
    (when (derived-mode-p 'org-mode)
      (when (org-in-regexp org-link-any-re)
        (let ((lnk (match-string-no-properties 2)))
          (if (string-match-p "https?://.+" (or lnk ""))
              (cons 'url lnk)
            (cons 'org-link (match-string-no-properties 0)))))))

  (embark-define-keymap jao-embark-targets-org-link-map
    "Actions for org links"
    ((kbd "RET") org-open-link-from-string))

  (defun jao-embark-targets--gl-org-link ()
    (when (org-in-regexp org-link-any-re)
      (cons 'gl-org-link (match-string-no-properties 0))))

  (embark-define-keymap jao-embark-targets-gl-org-link-map
    "Actions for exteranl org links"
    ((kbd "RET") org-open-at-point-global))

  (add-to-list 'embark-target-finders #'jao-embark-targets--gl-org-link)
  (add-to-list 'embark-keymap-alist
               '(gl-org-link . jao-embark-targets-gl-org-link-map))

  (add-to-list 'embark-target-finders #'jao-embark-targets--org-link)
  (add-to-list 'embark-keymap-alist
               '(org-link . jao-embark-targets-org-link-map))

url targets

  (declare-function w3m-anchor "w3m")

  (defun jao-embark-targets--w3m-anchor ()
    (when (not (region-active-p))
      (when-let ((url (or (jao-url-around-point)
                          (thing-at-point 'url)
                          (and (derived-mode-p 'w3m-mode)
                               (or (w3m-anchor) w3m-current-url))
                          (and (derived-mode-p 'eww-mode)
        (when (string-match-p "^https?.*" url)
          (cons 'url url)))))

  (add-to-list 'embark-target-finders #'jao-embark-targets--w3m-anchor)

  (defun jao-embark-url (url)
    "Browse URL, externally if we're already in an emacs browser."
    (if (derived-mode-p 'w3m-mode 'eww-mode)
        (jao-browse-with-external-browser url)
      (browse-url url)))

  (define-key embark-url-map (kbd "RET") #'jao-embark-url)
  (define-key embark-url-map (kbd "f") #'browse-url-firefox)
  (define-key embark-url-map (kbd "x") #'jao-rss-subscribe)
  (define-key embark-url-map (kbd "m") 'jao-browse-with-external-browser)

video url targets

  (defvar jao-embark-targets-video-sites
    '("youtu.be" "youtube.com" "blip.tv" "vimeo.com" "infoq.com"))

  (defun jao-embark--video-url-rx (&optional sites)
    (format "^https?://\\(?:www\\.\\)?%s/.+"
            (regexp-opt (or sites jao-embark-targets-video-sites) t)))

  (defvar jao-embark-targets-video-url-rx (jao-embark--video-url-rx)
    "A regular expression matching URLs that point to video streams")

  (defun jao-embark-targets--refine-url (_ url)
    (if (string-match-p jao-embark-targets-video-url-rx url)
        (cons 'video-url url)
      (cons 'url url)))

  (defun jao-embark-targets--play-video (player url)
    (interactive "sURL: ")
    (let ((cmd (format "%s %s" player (shell-quote-argument url))))
      (start-process-shell-command player nil cmd)))

  (defun jao-embark-targets-mpv (&optional url)
    "Play video stream with mpv"
    (interactive "sURL: ")
    (jao-embark-targets--play-video "mpv" url))

  (defun jao-embark-targets-vlc (&optional url)
    "Play video stream with vlc"
    (interactive "sURL: ")
    (jao-embark-targets--play-video "vlc" url))

  (embark-define-keymap jao-embark-targets-video-url-map
    "Actions on URLs pointing to remote video streams."
    :parent embark-url-map
    ("v" jao-embark-targets-mpv)
    ("RET" jao-embark-targets-vlc))

  (add-to-list 'embark-transformer-alist '(url . jao-embark-targets--refine-url))
  (add-to-list 'embark-keymap-alist '(video-url . jao-embark-targets-video-url-map))


  (with-eval-after-load "consult-spotify"
    (embark-define-keymap spotify-item-keymap
      "Actions for Spotify search results"
      ("y" espotify-yank-candidate-url)
      ("a" espotify-play-candidate-album)
      ("h" espotify-show-candidate-info))

    (add-to-list 'embark-keymap-alist
                 '(spotify-search-item . spotify-item-keymap)))