kijimad Emacs Config
Table of Contents
Emacs
Emacsの文芸的設定。
(require 'package) (setq package-archives '(("melpa" . "https://melpa.org/packages/") ("gnu" . "https://elpa.gnu.org/packages/") ("elpa" . "https://elpa.gnu.org/packages/") ("org" . "http://orgmode.org/elpa/")))
Org
org-modeはEmacsのキラーアプリの1つ。パッケージ名であり、ファイルの種類の1つ。ドキュメント管理にスケジュール、時間計測、コード評価を含めることができる。このドキュメントもorg-modeで書かれている。
base
(require 'org) (require 'org-protocol)
(setq system-time-locale "C")
(add-to-list 'auto-mode-alist '("\\.org$" . org-mode))
(setq org-startup-folded 'content)
(add-hook 'org-mode-hook 'turn-on-font-lock)
(setq org-startup-indented t)
(setq org-hide-leading-stars t) (setq org-hide-emphasis-markers t)
(setq org-startup-with-inline-images t)
(setq org-todo-keywords '((type "TODO" "WIP" "WAIT" "|" "DONE" "CLOSE"))) (setq org-todo-keyword-faces '(("TODO" . (:foreground "orange" :weight bold)) ("WIP" . (:foreground "DeepSkyBlue" :weight bold)) ("WAIT" . (:foreground "yellow" :weight bold)) ("DONE" . (:foreground "green" :weight bold)) ("CLOSE" . (:foreground "DarkOrchid" :weight bold))))
(setq org-src-fontify-natively t) (setq org-fontify-quote-and-verse-blocks t) (setq org-src-tab-acts-natively t)
;; (setq org-ellipsis "»") ;; (setq org-ellipsis "..") ;; (setq org-ellipsis "⤵") ;; (setq org-ellipsis "🢗") ;; (setq org-ellipsis "❖") ;; (setq org-ellipsis "↯") (setq org-ellipsis "▽")
(setq org-cycle-separator-lines 2)
(setq org-startup-truncated nil) (defun change-truncation() (interactive) (cond ((eq truncate-lines nil) (setq truncate-lines t)) (t (setq truncate-lines nil))))
(setq org-use-speed-commands t)
(define-key org-mode-map (kbd "C-c C-j") nil) (define-key org-mode-map (kbd "M-<left>") nil) (define-key org-mode-map (kbd "M-<right>") nil)
(define-key org-mode-map (kbd "C-c C-x i") 'org-clock-in) (define-key org-mode-map (kbd "C-c C-x o") 'org-clock-out)
(org-babel-do-load-languages 'org-babel-load-languages '((C . t) (clojure . t) (emacs-lisp . t) (graphql . t) (haskell . t) (lisp . t) (python . t) (ruby . t) (rust . t) (shell . t) (sql . t)))
(require 'cider) (setq org-babel-clojure-backend 'cider)
(setq inferior-lisp-program "clisp")
(add-hook 'sql-mode-org-src-hook #'sqlind-minor-mode)
(setq org-confirm-babel-evaluate nil)
(with-eval-after-load 'org ;; This is needed as of Org 9.2 (require 'org-tempo) (add-to-list 'org-structure-template-alist '("cj" . "src clojure")) (add-to-list 'org-structure-template-alist '("cl" . "src C")) (add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp")) (add-to-list 'org-structure-template-alist '("gp" . "src git-permalink")) (add-to-list 'org-structure-template-alist '("go" . "src go")) (add-to-list 'org-structure-template-alist '("gq" . "src graphql")) (add-to-list 'org-structure-template-alist '("hs" . "src haskell")) (add-to-list 'org-structure-template-alist '("js" . "src javascript")) (add-to-list 'org-structure-template-alist '("py" . "src python")) (add-to-list 'org-structure-template-alist '("rb" . "src ruby")) (add-to-list 'org-structure-template-alist '("rs" . "src rust")) (add-to-list 'org-structure-template-alist '("sc" . "src scala")) (add-to-list 'org-structure-template-alist '("sh" . "src shell")) (add-to-list 'org-structure-template-alist '("sq" . "src sql")) (add-to-list 'org-structure-template-alist '("ts" . "src typescript")) (add-to-list 'org-structure-template-alist '("mm" . "src mermaid")))
(require 'visual-fill-column) (defun kd/centering-buffer () "Centering buffer." (interactive) (setq visual-fill-column-width 100 visual-fill-column-center-text t) (visual-fill-column-mode 1)) (add-hook 'org-mode-hook (lambda () (kd/centering-buffer))) (add-hook 'eww-mode-hook (lambda () (kd/centering-buffer)))
(defun efs/org-font-setup () ;; Replace list hyphen with dot ;; (font-lock-add-keywords 'org-mode ;; '(("^ *\\([-]\\) " ;; (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "✦")))))) (dolist (face '((org-level-1 . 1.0) (org-level-2 . 1.0) (org-level-3 . 1.0) (org-level-4 . 1.0) (org-level-5 . 1.0) (org-level-6 . 1.0) (org-level-7 . 1.0) (org-level-8 . 1.0))) (set-face-attribute (car face) nil :font "Hiragino Sans" :height (cdr face) :weight 'bold)) (set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch) (set-face-attribute 'org-table nil :inherit 'fixed-pitch) (set-face-attribute 'org-formula nil :inherit 'fixed-pitch) (set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch)) (set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch)) (set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch)) (set-face-attribute 'org-special-keyword nil :inherit '(font-lock-comment-face fixed-pitch)) (set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face fixed-pitch)) (set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch) (set-face-attribute 'line-number nil :inherit 'fixed-pitch) (set-face-attribute 'line-number-current-line nil :inherit 'fixed-pitch) (custom-theme-set-faces 'user '(variable-pitch ((t (:family "Helvetica Neue" :height 1.0 :weight regular)))) '(fixed-pitch ((t (:family "Fira Mono" :height 1.0)))) '(org-block ((t (:inherit fixed-pitch)))) '(org-code ((t (:inherit (shadow fixed-pitch))))) '(org-document-info ((t (:foreground "dark orange")))) '(org-document-info-keyword ((t (:inherit (shadow fixed-pitch))))) '(org-indent ((t (:inherit (org-hide fixed-pitch))))) '(org-link ((t (:foreground "royal blue" :underline t)))) '(org-meta-line ((t (:inherit (font-lock-comment-face fixed-pitch))))) '(org-property-value ((t (:inherit fixed-pitch))) t) '(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch))))) '(org-table ((t (:inherit fixed-pitch :foreground "#f5f5f5")))) '(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.8)))) '(org-verbatim ((t (:inherit (shadow fixed-pitch))))) '(org-block-begin-line ((t (:inherit org-block))))))
themeのあとに評価するため、ここでは関数定義だけ。参考 https://github.com/daviwil/emacs-from-scratch/blob/master/Emacs.org
(add-hook 'org-mode-hook 'variable-pitch-mode) (add-hook 'org-mode-hook 'visual-line-mode)
(defun org-lint-dir (directory) (let* ((files (directory-files directory t ".*\\.org$"))) (org-lint-list files))) (defun org-lint-list (files) (cond (files (org-lint-file (car files)) (org-lint-list (cdr files))))) (defun org-lint-file (file) (let ((buf) (lint)) (setq buf (find-file-noselect file)) (with-current-buffer buf (if (setq lint (org-lint)) (print (list file lint))))))
babelで出力した結果はラップしないとtextlintでエラーになる。なのでデフォルトの設定に追加する。
(setq org-babel-default-header-args '((:session . "none") (:results . "replace") (:exports . "code") (:cache . "no") (:noweb . "no") (:hlines . "no") (:tangle . "no")(:wrap . "src")))
open-junk-file
;;; open-junk-file.el --- Open a junk (memo) file to try-and-error ;; $Time-stamp: <2016-09-13 10:59:40 rubikitch>$ ;; Copyright (C) 2010 rubikitch ;; Author: rubikitch <rubikitch@ruby-lang.org> ;; Keywords: convenience, tools ;; Package-Version: 20161210.1114 ;; Package-Commit: 558bec7372b0fed4c4cb6074ab906535fae615bd ;; URL: http://www.emacswiki.org/cgi-bin/wiki/download/open-junk-file.el ;; This file is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; This file is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs; see the file COPYING. If not, write to ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, ;; Boston, MA 02110-1301, USA. ;;; Commentary: ;; ;; M-x `open-junk-file' opens a new file whose filename is derived from ;; current time. You can write short program in it. It helps to ;; try-and-error programs. ;; ;; For example, in Emacs Lisp programming, use M-x `open-junk-file' ;; instead of *scratch* buffer. The junk code is SEARCHABLE. ;; ;; In Ruby programming, use M-x `open-junk-file' and ;; write a script with xmpfilter annotations. It is the FASTEST ;; methodology to try Ruby methods, Irb is not needed anymore. ;; Xmpfilter is available at http://eigenclass.org/hiki/rcodetools ;;; Commands: ;; ;; Below are complete command list: ;; ;; `open-junk-file' ;; Open a new file whose filename is derived from current time. ;; ;;; Customizable Options: ;; ;; Below are customizable option list: ;; ;; `open-junk-file-format' ;; *File format to put junk files with directory. ;; default = "~/junk/%Y/%m/%d-%H%M%S." ;; `open-junk-file-find-file-function' ;; *Function to open junk files. ;; default = (quote find-file-other-window) ;;; Installation: ;; ;; Put open-junk-file.el to your load-path. ;; The load-path is usually ~/elisp/. ;; It's set in your ~/.emacs like this: ;; (add-to-list 'load-path (expand-file-name "~/elisp")) ;; ;; And the following to your ~/.emacs startup file. ;; ;; (require 'open-junk-file) ;; ;; No need more. ;;; Customize: ;; ;; ;; All of the above can customize by: ;; M-x customize-group RET open-junk-file RET ;; ;;; Bug Report: ;; ;; If you have problem, send a bug report via M-x open-junk-file-send-bug-report. ;; The step is: ;; 0) Setup mail in Emacs, the easiest way is: ;; (setq user-mail-address "your@mail.address") ;; (setq user-full-name "Your Full Name") ;; (setq smtpmail-smtp-server "your.smtp.server.jp") ;; (setq mail-user-agent 'message-user-agent) ;; (setq message-send-mail-function 'message-smtpmail-send-it) ;; 1) Be sure to use the LATEST version of open-junk-file.el. ;; 2) Enable debugger. M-x toggle-debug-on-error or (setq debug-on-error t) ;; 3) Use Lisp version instead of compiled one: (load "open-junk-file.el") ;; 4) Do it! ;; 5) If you got an error, please do not close *Backtrace* buffer. ;; 6) M-x open-junk-file-send-bug-report and M-x insert-buffer *Backtrace* ;; 7) Describe the bug using a precise recipe. ;; 8) Type C-c C-c to send. ;; # If you are a Japanese, please write in Japanese:-) ;;; Code: (eval-when-compile (require 'cl)) (defgroup open-junk-file nil "open-junk-file" :group 'files) (defcustom open-junk-file-format "~/junk/%Y/%m/%d-%H%M%S." "File format to put junk files with directory. It can include `format-time-string' format specifications." :type 'string :group 'open-junk-file) (defvaralias 'open-junk-file-format 'open-junk-file-directory) (defcustom open-junk-file-find-file-function 'find-file-other-window "Function to open junk files." :type 'function :group 'open-junk-file) (defcustom open-junk-file-hook nil "List of functions to be called after a buffer is loaded from a `junk' file. Whether the file is a JUNK or not is infered by `open-junk-file-format'.") ;;;###autoload (defun find-file-hook--open-junk-file () "Run `open-junk-file-hook' when the file is a JUNK file." (when (string-prefix-p (file-truename (replace-regexp-in-string "%.+$" "" open-junk-file-format)) (file-truename buffer-file-name)) (run-hooks 'open-junk-file-hook))) ;;;###autoload (add-hook 'find-file-hook 'find-file-hook--open-junk-file) ;;;###autoload (defun open-junk-file (&optional format find-file-fn) "Open a new file whose filename is derived from current time. You can write short program in it. It helps to try-and-error programs. For example, in Emacs Lisp programming, use M-x `open-junk-file' instead of *scratch* buffer. The junk code is SEARCHABLE. FORMAT and FIND-FILE-FN are optional. Default value of them are `open-junk-file-format' and `open-junk-file-find-file-function'." (interactive) (let* ((file (format-time-string (or format open-junk-file-format) (current-time))) (dir (file-name-directory file))) (make-directory dir t) (funcall (or find-file-fn open-junk-file-find-file-function) (read-string "Junk Code (Enter extension): " file)))) ;;;; Bug report (defvar open-junk-file-maintainer-mail-address (concat "rubiki" "tch@ru" "by-lang.org")) (defvar open-junk-file-bug-report-salutation "Describe bug below, using a precise recipe. When I executed M-x ... How to send a bug report: 1) Be sure to use the LATEST version of open-junk-file.el. 2) Enable debugger. M-x toggle-debug-on-error or (setq debug-on-error t) 3) Use Lisp version instead of compiled one: (load \"open-junk-file.el\") 4) If you got an error, please paste *Backtrace* buffer. 5) Type C-c C-c to send. # If you are a Japanese, please write in Japanese:-)") (defun open-junk-file-send-bug-report () (interactive) (reporter-submit-bug-report open-junk-file-maintainer-mail-address "open-junk-file.el" (apropos-internal "^open-junk-file-" 'boundp) nil nil open-junk-file-bug-report-salutation)) (provide 'open-junk-file) ;; How to save (DO NOT REMOVE!!) ;; (emacswiki-post "open-junk-file.el") ;;; open-junk-file.el ends here
(use-package open-junk-file) (setq open-junk-file-format (concat "~/Private/junk/%Y-%m-%d-%H%M%S.")) (global-set-key (kbd "C-x C-z") 'open-junk-file)
見出しをいい感じにするパッケージ。だが、org-modernに上書きされてしまうので使ってない。
org-superstar
(require 'org-superstar) ;; (add-hook 'org-mode-hook (lambda () (org-superstar-mode 1))) ;; (setq org-superstar-headline-bullets-list '("🙐" "🙑" "🙒" "🙓" "🙔" "🙕" "🙖" "🙗")) ;; (setq org-superstar-headline-bullets-list '("◉" "○" "●" "✿" "✸")) ;; (setq org-superstar-item-bullet-alist '((?* . ?•) ;; (?+ . ?») ;; (?- . ?➤)))
org-modern
org-modernはorg-modeの外観をいい感じにするパッケージ。
(add-hook 'org-mode-hook #'org-modern-mode) (add-hook 'org-agenda-finalize-hook #'org-modern-agenda)
org-tree-slide
org-tree-slideはorg-modeでスライド表示するパッケージ。
(org-tree-slide-presentation-profile) (org-tree-slide--hide-slide-header)
org-journal
org-journalは日付ごとのファイルを生成したり、時刻を挿入できるパッケージ。
(require 'org-journal)
(setq org-journal-date-format "%Y-%m-%d(%a)") (setq org-journal-time-format "%R ")
(setq org-journal-dir (concat "~/Private/junk/diary/org-journal"))
(setq org-journal-file-format "%Y%m%d.org")
(setq org-journal-find-file 'find-file)
(setq org-journal-hide-entries-p nil)
(defun kd/new-buffer-p () (not (file-exists-p (buffer-file-name)))) (defun kd/insert-journal-template () (let ((template-file (expand-file-name "~/.emacs.d/resources/journal-template.org" org-directory))) (when (kd/new-buffer-p) (save-excursion (goto-char (point-min)) (insert-file-contents template-file))))) (add-hook 'org-journal-after-entry-create-hook #'kd/insert-journal-template)
org-roam
org-roamはorgファイルをsqliteによって管理しやすくしたパッケージ。orgファイル同士の関連を挿入したり、リンク元のファイルを一覧にする、といったことができる。sqliteに保存されるので、別でクエリを使って取り出してグラフ描画に使ったりも可能。
(require 'org-roam) (add-hook 'after-init-hook 'org-roam-mode) (make-directory "~/roam" t) (setq org-roam-v2-ack t) (setq org-roam-directory "~/roam") (setq org-roam-completion-everywhere t) (setq org-id-link-to-org-use-id t) (setq org-id-extra-files (org-roam--list-files org-roam-directory)) (org-roam-setup)
(define-key global-map (kbd "C-c n f") 'org-roam-node-find) (define-key global-map (kbd "C-c n g") 'org-roam-graph) (define-key global-map (kbd "C-c n i") 'org-roam-node-insert) (define-key global-map (kbd "C-c n r") 'org-roam-node-random) (define-key global-map (kbd "C-c n l") 'org-roam-buffer-toggle) (define-key global-map (kbd "C-M-i") 'completion-at-point)
(setq my-todo-file "~/roam/20230202234553-inbox.org") (setq org-roam-capture-templates '(("t" "TODO" entry (file+headline my-todo-file "Inbox") "*** TODO %?\n") ("d" "default" plain "%?" :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}")) ("r" "roam-page" plain (file "~/roam/templates/roam-page.org") :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}")) ("p" "project" plain (file "~/roam/templates/project.org") :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+filetags: Project")) ))
org-alert
org-alertはorg scheduleの項目を時間経過で通知してくれるパッケージ。
(require 'org-alert) (setq alert-default-style 'notifications) (setq org-alert-interval 300) (setq org-alert-notification-title "Reminder") (org-alert-enable)
denote
denoteはシンプルなノートパッケージ。
(require 'denote-org-dblock) (setq denote-directory (expand-file-name "~/roam")) (setq denote-known-keywords '("essay" "code" "book" "term" "memo" "draft")) (define-key global-map (kbd "C-c d") 'denote-create-note) ;; カスタムテンプレート ;; roamで表示できるIDを追加 (setq denote-org-front-matter ":properties: :ID: %4$s :end: #+title: KDOC n: %1$s #+date: %2$s #+filetags: :draft%3$s #+identifier: %4$s \n")
(use-package denote-menu :straight (:host github :repo "namilus/denote-menu"))
(setq denote-templates `((entry . ,(f-read-text "~/.emacs.d/resources/entry.org"))))
org-agenda
org-agendaはorg-modeでtodo管理する機能。
(define-key global-map "\C-cl" 'org-store-link) (define-key global-map "\C-ca" 'org-agenda) (define-key global-map "\C-cc" 'org-capture) (defun org-agenda-default () (interactive) ;; mini-bufferを開いている間にpersp-switchが走ると、プロンプトが残り続けるのを防ぐ (when (window-minibuffer-p) (minibuffer-keyboard-quit)) (persp-switch "2") (org-agenda nil "z")) (global-set-key (kbd "<f6>") 'org-agenda-default)
(add-hook 'org-pomodoro-short-break-finished-hook 'org-agenda-default) (add-hook 'org-pomodoro-long-break-finished-hook 'org-agenda-default)
(setq org-capture-templates '(("m" "Memo" entry (file+headline my-todo-file "Memo") "** %?\n") ("t" "Task" entry (file+headline my-todo-file "Tasks") "** TODO %?\n") ("p" "Protocol" entry (file+headline my-todo-file "Inbox") "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?") ("L" "Protocol Link" entry (file+headline my-todo-file "Inbox") "* %?[[%:link][%:description]]")))
(setq org-log-done t)
(let* ((my-org-directory (concat "~/Private/junk/diary/org-journal/")) (my-todo-file (concat my-org-directory "todo.org")) (my-roam-file "~/roam") (my-agenda-files nil)) (if (file-exists-p my-todo-file) (setq my-agenda-files (push my-todo-file my-agenda-files))) (if (file-exists-p my-roam-file) (setq my-agenda-files (push my-roam-file my-agenda-files))) (setq org-agenda-files my-agenda-files) (setq org-directory my-org-directory) (setq org-default-notes-file my-todo-file))
(setq org-agenda-start-with-log-mode t)
(setq org-agenda-span 14) (setq org-agenda-start-day "7d")
(setq org-agenda-custom-commands '(("z" "Super zaen view" ((agenda "" ((org-agenda-span 'day) (org-super-agenda-groups '((:name "🏗️Today" :time-grid t :date today :scheduled today :order 1) (:name "Overdue" :deadline past :scheduled past :order 3) (:habit t) (:log t) (:discard (:anything)))))) (alltodo "" ((org-agenda-overriding-header "") (org-super-agenda-groups '((:name "▶️Work In Progress" :todo "WIP" :order 1) (:name "🔦Next" :effort> "0:01" :order 5) (:name "✍To write" :tag "Write" :order 12) (:name "📕To read" :tag "Read" :order 14) (:name "✍Things I Don't Know" :tag "DontKnow" :order 15) (:name "🛤️Train" :tag "Train" :order 18) (:name "🍵TODO" :todo "TODO" :order 20) (:discard (:anything t))))))))))
(setq org-clocktable-defaults '(:maxlevel 3 :scope agenda :tags "" :block today :step day :stepskip0 true :fileskip0 true))
(setq spacemacs-theme-org-agenda-height nil org-agenda-skip-scheduled-if-done t org-agenda-skip-deadline-if-done t org-agenda-include-deadlines t org-agenda-include-diary t org-agenda-block-separator nil org-agenda-compact-blocks t org-agenda-start-with-log-mode t org-habit-following-days 7 org-habit-preceding-days 10 org-habit-graph-column 80 ;; 見出しが隠れるため org-habit-show-habits t)
- org-roamの長いファイル名が表示されてうざいので省略する
- フォーマットのeはorg-effort
(setq org-agenda-prefix-format `((agenda . " %i %-12(vulpea-agenda-category)%?-12t% s") (todo . " %i %-12(vulpea-agenda-category)%?-12t%-6e% s") (tags . " %i %-12(vulpea-agenda-category) ") (search . " %i %-12(vaulpea-agenda-category) "))) ;; original -> https://d12frosted.io/posts/2020-06-24-task-management-with-roam-vol2.html (defun vulpea-agenda-category () (let* ((title (vulpea-buffer-prop-get "title"))) title)) (defun vulpea-buffer-prop-get (name) "Get a buffer property called NAME as a string." (org-with-point-at 1 (if (re-search-forward (concat "^#\\+" name ": \\(.*\\)") (point-max) t) (buffer-substring-no-properties (match-beginning 1) (match-end 1)) "")))
org-super-agenda
org-super-agendaは詳細に設定できるagenda表示ができるパッケージ。
(org-super-agenda-mode) (let ((org-super-agenda-groups '(;; Each group has an implicit boolean OR operator between its selectors. (:name "Today" ; Optionally specify section name :time-grid t ; Items that appear on the time grid :todo "TODAY") ; Items that have this TODO keyword (:name "Important" ;; Single arguments given alone :tag "bills" :priority "A") (:name "WIP" ;; Single arguments given alone :todo "WIP") ;; Set order of multiple groups at once (:order-multi (2 (:name "Shopping in town" ;; Boolean AND group matches items that match all subgroups :and (:tag "shopping" :tag "@town")) (:name "Food-related" :habit t ;; Multiple args given in list with implicit OR :tag ("food" "dinner")) (:name "Space-related (non-moon-or-planet-related)" ;; Regexps match case-insensitively on the entire entry :and (:regexp ("space" "NASA") ;; Boolean NOT also has implicit OR between selectors :not (:regexp "moon" :tag "planet"))))) ;; Groups supply their own section names when none are given (:todo ("SOMEDAY" "TO-READ" "TO-WRITE" "CHECK" "TO-WATCH" "WATCHING") ;; Show this group at the end of the agenda (since it has the ;; highest number). If you specified this group last, items ;; with these todo keywords that e.g. have priority A would be ;; displayed in that group instead, because items are grouped ;; out in the order the groups are listed. :order 9) (:priority<= "B" ;; Show this section after "Today" and "Important", because ;; their order is unspecified, defaulting to 0. Sections ;; are displayed lowest-number-first. :order 1) ;; After the last group, the agenda will display items that didn't ;; match any of these groups, with the default order position of 99 ))) ;; (org-agenda nil "a") )
org-pomodoro
org-pomodoro用の設定。
(require 'org-pomodoro)
(define-key global-map [insert] 'org-pomodoro)
(setq org-pomodoro-short-break-length 0) (setq org-pomodoro-long-break-length 10) (setq org-pomodoro-expiry-time 120)
(setq org-pomodoro-finished-sound "~/.emacs.d/resources/atos.wav") (setq org-pomodoro-short-break-sound "~/.emacs.d/resources/atos.wav") (setq org-pomodoro-long-break-sound "~/.emacs.d/resources/atos.wav") ;; テスト ;; (org-pomodoro-finished) ;; (org-pomodoro-short-break-finished)
(add-hook 'org-pomodoro-short-break-finished-hook 'org-agenda-default) (add-hook 'org-pomodoro-long-break-finished-hook 'org-agenda-default)
(setq org-clock-mode-line-total 'all)
(defun kd/org-pomodoro-remain-gauge (max-minutes) "Display remain time gauge." (let* ((display-len 25) (remaining-minutes (/ (org-pomodoro-remaining-seconds) 60)) (current-percent (/ remaining-minutes max-minutes)) (done (truncate (* (- 1 current-percent) display-len))) (will (truncate (* current-percent display-len)))) (concat "%{T2}" ;; (concat "%{F#008000}" (make-string done ?█) "%{F-}") (concat "%{F#008000}" (make-string done ?|) "%{F-}") (concat "%{F#413839}" (make-string will ?|) "%{F-}") "%{T-}"))) (defun kd/org-pomodoro-time () "Return the remaining pomodoro time. Function for displaying in Polybar." (cond ((org-pomodoro-active-p) (cl-case org-pomodoro-state (:pomodoro (format "%s %dm %s%s%s" (kd/org-pomodoro-remain-gauge org-pomodoro-length) (/ (org-pomodoro-remaining-seconds) 60) "%{F#FFFFFF}" org-clock-heading "%{F-}" )) (:short-break (format "%s Short break: %dm" (kd/org-pomodoro-remain-gauge org-pomodoro-short-break-length) (/ (org-pomodoro-remaining-seconds) 60))) (:long-break (format "%s Long break: %dm" (kd/org-pomodoro-remain-gauge org-pomodoro-long-break-length) (/ (org-pomodoro-remaining-seconds) 60))) (:overtime (format "Overtime! %dm" (/ (org-pomodoro-remaining-seconds) 60))) )) ((org-clocking-p) (format "(%s) %s" (org-clock-get-clocked-time) org-clock-heading)) (t "OFF"))) (defun kd/effort-timer () (cond ((and (not org-clock-effort) (or (org-pomodoro-active-p) (org-clocking-p)) "effort not set!")) ((and org-clock-effort (or (org-pomodoro-active-p) (org-clocking-p))) (format "[%s/%s]" (org-duration-from-minutes (org-clock-get-clocked-time)) org-clock-effort)) (t ""))) (defun kd/pmd-today-point-display () (let* ((all-minute (* kd/pmd-today-point 25)) (hour (/ all-minute 60)) (minute (% all-minute 60))) (format " %s %dpts/%02dh%02dm" (kd/effort-timer) kd/pmd-today-point hour minute )))
(defvar kd/pmd-today-point 0) (add-hook 'org-pomodoro-finished-hook (lambda () (setq kd/pmd-today-point (1+ kd/pmd-today-point)))) (defun kd/write-pmd (str) (shell-command (format "echo '%s' >> ~/roam/pmd.csv" str))) ;; reset point (run-at-time "23:59pm" (* 24 60 60) (lambda () (when (> kd/pmd-today-point 0) (kd/write-pmd (concat (format-time-string "%Y-%m-%d") ", " (number-to-string kd/pmd-today-point))) (setq kd/pmd-today-point 0) (message "pomodoro count reset!"))))
(defun kd/pmd-manual () "set point manually" (interactive) (let ((point (read-from-minibuffer "How much point? "))) (setq kd/pmd-today-point (string-to-number point))))
org-effort
- org-clock-effort
- mode-line-format
- org-pomodoro-mode-line
org-tag
タグを選択できるようにする。
(setq org-tag-alist '(("Write" . ?w) ("Read" . ?r) ("DontKnow" . ?d) ("Train" . ?t)))
Mermaid
Mermaid JSはテキストから図を描画するライブラリ。
コマンドをインストールすることなく実行するためにDockerを使う設定。
(require 'mermaid-mode)
(setq mermaid-mmdc-location "docker") (setq mermaid-flags '(concat "run --rm -u 1000 -v /tmp:/tmp -v " (projectile-project-root) ":" (projectile-project-root) " ghcr.io/mermaid-js/mermaid-cli/mermaid-cli:9.1.6"))
(defun org-babel-execute:mermaid (body params) "Execute command with BODY and PARAMS from src block." (let* ((out-file (or (cdr (assoc :file params)) (error "Mermaid requires a \":file\" header argument"))) (temp-file (org-babel-temp-file "mermaid-")) (cmd (concat (shell-quote-argument mermaid-mmdc-location) " " (eval mermaid-flags) " -o " (org-babel-process-file-name out-file) " -i " temp-file ))) (with-temp-file temp-file (insert body)) (org-babel-eval cmd "") nil))
(defun kd/random-alnum () (let* ((alnum "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") (i (% (abs (random)) (length alnum)))) (substring alnum i (1+ i)))) (defun kd/random-letter-string (num) (interactive) (let ((str "")) (dotimes (num num) (setq str (concat str (kd/random-alnum))) ) str)) (defun kd/timestamp () (let* ((date org-agenda-current-date) (y (nth 2 date)) (d (nth 1 date)) (m (nth 0 date)) (time (format-time-string "%H%M%S" (current-time)))) (format "%04d%02d%02d%s" y m d time))) (defun kd/insert-rand-png () (interactive) (insert (concat "images/" (kd/timestamp) "-" (kd/random-letter-string 10) ".png")))
(add-hook 'org-babel-after-execute-hook 'org-redisplay-inline-images)
Font
フォント設定。
(when window-system (progn (pcase system-type ((or 'gnu/linux 'windows-nt 'cygwin) (set-face-attribute 'default nil :font "Fira Code" :weight 'regular :height 110) (set-fontset-font nil 'japanese-jisx0208 (font-spec :family "Hiragino Sans"))) ;; Mac ('darwin (set-face-attribute 'default nil :font "Fira Mono" :height 150) (set-fontset-font nil 'japanese-jisx0208 (font-spec :family "Hiragino Sans"))))))
いい感じのフォントリスト。
- JetBrains Mono
- Iosevka SS08
- Fira Mono
- Fira Code
- Hiragino Sans – japanese
- Hack
(prefer-coding-system 'utf-8)
(set-language-environment 'utf-8)
(set-terminal-coding-system 'utf-8)
(set-keyboard-coding-system 'utf-8)
(set-buffer-file-coding-system 'utf-8)
(setq default-buffer-file-coding-system 'utf-8)
(setq file-name-coding-system 'utf-8)
(set-default-coding-systems 'utf-8)
(defun --set-emoji-font (frame) "Adjust the font settings of FRAME so Emacs can display emoji properly." (if (eq system-type 'darwin) ;; For NS/Cocoa (set-fontset-font t 'symbol (font-spec :family "Apple Color Emoji") frame 'prepend) ;; For Linux (set-fontset-font t 'symbol (font-spec :family "Symbola") frame 'prepend))) (when window-system (progn ;; GUI用設定 (--set-emoji-font nil) ;; Hook for when a frame is created with emacsclient ;; see https://www.gnu.org/software/emacs/manual/html_node/elisp/Creating-Frames.html (add-hook 'after-make-frame-functions '--set-emoji-font) ;; unicodefont (require 'unicode-fonts) (unicode-fonts-setup)))
Simple
未分類の設定。最初から入っているものの設定。
(server-start)
(setq initial-scratch-message "")
(setq confirm-kill-processes nil)
(menu-bar-mode 0)
(show-paren-mode t)
(setq inhibit-startup-message t)
(setq save-silently t)
(global-font-lock-mode t)
(setq frame-title-format "%f")
(setq ring-bell-function 'ignore)
(require 'scroll-bar) (scroll-bar-mode 0)
(show-paren-mode t)
(require 'tool-bar) (tool-bar-mode 0)
(tooltip-mode 0)
(global-set-key (kbd "M-n") (lambda () (interactive) (scroll-up 1))) (global-set-key (kbd "M-p") (lambda () (interactive) (scroll-down 1)))
(keyboard-translate ?\C-h ?\C-?)
(global-set-key "\C-xp" 'count-words)
(global-set-key (kbd "C-M-{") 'shrink-window-horizontally) (global-set-key (kbd "C-M-}") 'enlarge-window-horizontally)
(defalias 'yes-or-no-p 'y-or-n-p)
(setq confirm-kill-emacs 'y-or-n-p)
(setq vc-follow-symlinks t)
(require 'smartparens) (add-hook 'prog-mode-hook 'smartparens-mode) (add-hook 'eshell-mode-hook 'smartparens-mode) (add-hook 'org-mode-hook 'smartparens-mode)
(setq message-log-max 1000)
(setq history-length 500)
(setq history-delete-duplicates t)
(setq backup-inhibited t) (setq make-backup-files nil) (setq auto-save-default nil) (setq create-lockfiles nil)
(setq delete-auto-save-files t)
(setq auto-save-timeout 2) (setq auto-save-visited-interval 2) (setq auto-save-no-message t) (auto-save-visited-mode)
(setq-default bidi-display-reordering nil)
(setq inhibit-splash-screen t)
(display-line-numbers-mode)
(setq ediff-window-setup-function 'ediff-setup-windows-plain)
(setq-default indent-tabs-mode nil)
(setq x-select-enable-primary t)
(add-hook 'before-save-hook 'delete-trailing-whitespace)
(delete-selection-mode t)
(eval-after-load "django-mode" '(progn (define-key django-mode-map (kbd "C-t") nil))) (eval-after-load "dired" '(progn (define-key dired-mode-map (kbd "C-t") nil))) (eval-after-load "vterm" '(progn (define-key vterm-mode-map (kbd "C-t") nil) (define-key vterm-mode-map (kbd "M-<right>") nil) (define-key vterm-mode-map (kbd "M-<left>") nil) (define-key vterm-mode-map (kbd "<f9>") nil) (define-key vterm-mode-map (kbd "C-<f9>") nil))) (eval-after-load "magit" '(progn (mapc (lambda (i) (define-key magit-mode-map (kbd (format "M-%d" i)) nil)) (number-sequence 1 4))))
(defadvice isearch-mode (around isearch-mode-default-string (forward &optional regexp op-fun recursive-edit word-p) activate) (if (and transient-mark-mode mark-active (not (eq (mark) (point)))) (progn (isearch-update-ring (buffer-substring-no-properties (mark) (point))) (deactivate-mark) ad-do-it (if (not forward) (isearch-repeat-backward) (goto-char (mark)) (isearch-repeat-forward))) ad-do-it))
(setq ;; ホイールでスクロールする行数を設定 mouse-wheel-scroll-amount '(1 ((shift) . 2) ((control))) ;; 速度を無視する mouse-wheel-progressive-speed nil) (setq scroll-preserve-screen-position 'always)
(if (fboundp 'blink-cursor-mode)
(blink-cursor-mode -1))
(put 'upcase-region 'disabled nil)
(setq native-comp-async-report-warnings-errors nil)
Packages
未分類の設定。拡張設定。
(savehist-mode 1)
(push 'compile-command savehist-additional-variables)
(push 'command-history savehist-ignored-variables)
(require 'rainbow-delimiters) (rainbow-delimiters-mode t) (add-hook 'prog-mode-hook 'rainbow-delimiters-mode)
(require 'auto-highlight-symbol) (global-auto-highlight-symbol-mode t) (ahs-set-idle-interval 0.4)
(define-key auto-highlight-symbol-mode-map (kbd "M-<right>") nil) (define-key auto-highlight-symbol-mode-map (kbd "M-<left>") nil)
(require 'whitespace) ;; 空白 (set-face-foreground 'whitespace-space nil) (set-face-background 'whitespace-space "gray33") ;; ファイル先頭と末尾の空行 (set-face-background 'whitespace-empty "gray33") ;; タブ (set-face-foreground 'whitespace-tab nil) (set-face-background 'whitespace-tab "gray33") ;; ??? (set-face-background 'whitespace-trailing "gray33") (set-face-background 'whitespace-hspace "gray33") (setq whitespace-style '(face ; faceで可視化 trailing ; 行末 tabs ; タブ empty ; 先頭/末尾の空行 spaces ; 空白 ;; space-mark ; 表示のマッピング tab-mark)) ;; スペースは全角のみを可視化 (setq whitespace-space-regexp "\\(\u3000+\\)") ;; タブの表示を変更 (setq whitespace-display-mappings '((tab-mark ?\t [?\xBB ?\t]))) (global-whitespace-mode 1)
(add-hook 'emacs-lisp-mode-hook (lambda () (setq indent-tabs-mode nil))) (setq-default typescript-indent-level 2)
(require 'hl-line) (defun global-hl-line-timer-function () (global-hl-line-unhighlight-all) (let ((global-hl-line-mode t)) (global-hl-line-highlight))) (setq global-hl-line-timer (run-with-idle-timer 0.03 t 'global-hl-line-timer-function))
(defface hlline-face '((((class color) (background dark)) (:background "DodgerBlue4")) (((class color) (background light)) (:background "gainsboro")) (t ())) "*Face used by hl-line.") (setq hl-line-face 'hlline-face) (global-hl-line-mode)
(setq beacon-size 20) ; default 40 (setq beacon-color "#827591") (setq beacon-blink-when-focused t) (beacon-mode)
(setq-default bm-buffer-persistence nil) (setq bm-restore-repository-on-load t) (require 'bm) (add-hook 'find-file-hook 'bm-buffer-restore) (add-hook 'kill-buffer-hook 'bm-buffer-save) (add-hook 'after-save-hook 'bm-buffer-save) (add-hook 'after-revert-hook 'bm-buffer-restore) (add-hook 'vc-before-checkin-hook 'bm-buffer-save) (add-hook 'kill-emacs-hook '(lambda nil (bm-buffer-save-all) (bm-repository-save))) (global-set-key (kbd "C-M-SPC") 'bm-toggle) (global-set-key (kbd "M-[") 'bm-previous) (global-set-key (kbd "M-]") 'bm-next)
(global-set-key (kbd "M-<left>") 'previous-buffer) (global-set-key (kbd "M-<right>") 'next-buffer) (global-set-key (kbd "C-t") 'other-window) (global-set-key (kbd "M-t") (lambda () (interactive) (other-window -1)))
(require 'ace-jump-mode) (setq ace-jump-mode-gray-background nil) (setq ace-jump-word-mode-use-query-char nil) (setq ace-jump-mode-move-keys (append "asdfghjkl;:]qwertyuiop@zxcvbnm,." nil)) (global-set-key (kbd "C-o") 'ace-jump-word-mode)
(ace-link-setup-default)
(require 'avy) (global-set-key (kbd "C-j") 'avy-copy-line) (global-set-key (kbd "M-j") 'avy-goto-line) (global-set-key (kbd "C-M-j") 'avy-goto-whitespace-end)
(require 'migemo) (when (and (executable-find "cmigemo") (require 'migemo nil t)) (setq migemo-command my-migemo-command) (setq migemo-options '("-q" "--emacs")) (setq migemo-dictionary my-migemo-dictionary) (setq migemo-user-dictionary nil) (setq migemo-regex-dictionary nil) (setq migemo-coding-system 'utf-8-unix) (load-library "migemo") (migemo-init) )
(require 'anzu) (global-anzu-mode)
(require 'magit) (global-set-key (kbd "C-x g") 'magit-status) (with-eval-after-load 'magit (require 'forge))
(global-git-gutter+-mode 1)
(global-set-key (kbd "C-c C-v") 'git-gutter+-show-hunk-inline-at-point)
;; http://www.modernemacs.com/post/pretty-magit/ (defun kd/magit-commit-prompt () "Use ivy to insert conventional commit keyword." (let ((conventional-prompt '(("build" "ビルド") ("chore" "雑事, カテゴライズする必要ないようなもの") ("ci" "CI") ("docs" "ドキュメント") ("feat" "新機能") ("fix" "バグフィックス") ("perf" "パフォーマンス") ("refactor" "リファクタリング") ("revert" "コミット取り消し") ("style" "コードスタイル修正") ("test" "テスト")))) (insert (concat (ivy-read "Commit Type " (mapcar 'car conventional-prompt) :require-match t :sort t :preselect "Add: ") ": ")))) (remove-hook 'git-commit-setup-hook 'with-editor-usage-message) (add-hook 'git-commit-setup-hook 'kd/magit-commit-prompt)
(require 'mozc) (set-language-environment "Japanese") (setq default-input-method "japanese-mozc") (global-set-key (kbd "C-SPC") 'toggle-input-method) (add-hook 'input-method-activate-hook (lambda() (set-cursor-color "Magenta"))) (add-hook 'input-method-deactivate-hook (lambda() (set-cursor-color "grey")))
(require 'mozc-popup) (setq mozc-candidate-style 'echo-area)
(global-set-key (kbd "<f2>") 'devdocs-search)
(require 'fish-mode)
(auto-insert-mode) (setq auto-insert-directory "~/.emacs.d/insert/") (setq auto-insert-alist (append '( ("\\.sh$" . "shell-template.sh") ) auto-insert-alist))
(require 'yasnippet) (add-to-list 'yas-snippet-dirs "~/.emacs.d/snippets") (auto-insert-mode t) (yas-global-mode t) (setq yas-prompt-functions '(yas-ido-prompt)) (define-key yas-minor-mode-map (kbd "C-x y i") 'yas-insert-snippet) (define-key yas-minor-mode-map (kbd "C-x y n") 'yas-new-snippet) (define-key yas-minor-mode-map (kbd "C-x y v") 'yas-visit-snippet-file)
(require 'projectile) (projectile-global-mode) (define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map)
(defun revert-buffer-no-confirm (&optional force-reverting) "Interactive call to revert-buffer. Ignoring the auto-save file and not requesting for confirmation. When the current buffer is modified, the command refuses to revert it, unless you specify the optional argument: force-reverting to true." (interactive "P") ;;(message "force-reverting value is %s" force-reverting) (if (or force-reverting (not (buffer-modified-p))) (revert-buffer :ignore-auto :noconfirm) (error "The buffer has been modified"))) (global-set-key (kbd "<f5>") 'revert-buffer-no-confirm)
(global-auto-revert-mode 1)
(require 'tramp) (setq tramp-default-method "ssh")
(require 'flycheck) (setq flycheck-indication-mode 'right-fringe) (add-hook 'flycheck-mode-hook #'flycheck-set-indication-mode) (eval-after-load 'flycheck '(add-hook 'flycheck-mode-hook #'flycheck-cask-setup)) (add-hook 'emacs-lisp-mode-hook 'flycheck-mode) (add-hook 'python-mode-hook 'flycheck-mode) (add-hook 'ruby-mode-hook 'flycheck-mode) ;; 自動起動 (setq flycheck-check-syntax-automatically '(save idle-change mode-enabled)) ;; コード変更後、2秒後にチェックする (setq flycheck-idle-change-delay 2)
(which-key-mode) (which-key-setup-side-window-bottom)
(require 'dired-single) (defun my-dired-init () "Bunch of stuff to run for dired, either immediately or when it's loaded." ;; <add other stuff here> (define-key dired-mode-map [remap dired-find-file] 'dired-single-buffer) (define-key dired-mode-map [remap dired-mouse-find-file-other-window] 'dired-single-buffer-mouse) (define-key dired-mode-map [remap dired-up-directory] 'dired-single-up-directory)) ;; if dired's already loaded, then the keymap will be bound (if (boundp 'dired-mode-map) ;; we're good to go; just add our bindings (my-dired-init) ;; it's not loaded yet, so add our bindings to the load-hook (add-hook 'dired-load-hook 'my-dired-init)) (add-hook 'dired-mode-hook 'all-the-icons-dired-mode) (add-hook 'dired-mode-hook 'dired-hide-details-mode)
(require 'easy-kill) (global-set-key [remap kill-ring-save] 'easy-kill) (require 'easy-kill-extras) ;; easy-kill-extras ;; Upgrade `mark-word' and `mark-sexp' with easy-mark ;; equivalents. (global-set-key (kbd "M-@") 'easy-mark-word) (global-set-key (kbd "C-M-@") 'easy-mark-sexp) ;; `easy-mark-to-char' or `easy-mark-up-to-char' could be a good ;; replacement for `zap-to-char'. (global-set-key [remap zap-to-char] 'easy-mark-to-char) ;; Add the following tuples to `easy-kill-alist', preferrably by ;; using `customize-variable'. (add-to-list 'easy-kill-alist '(?^ backward-line-edge "")) (add-to-list 'easy-kill-alist '(?$ forward-line-edge "")) (add-to-list 'easy-kill-alist '(?b buffer "")) (add-to-list 'easy-kill-alist '(?< buffer-before-point "")) (add-to-list 'easy-kill-alist '(?> buffer-after-point "")) (add-to-list 'easy-kill-alist '(?f string-to-char-forward "")) (add-to-list 'easy-kill-alist '(?F string-up-to-char-forward "")) (add-to-list 'easy-kill-alist '(?t string-to-char-backward "")) (add-to-list 'easy-kill-alist '(?T string-up-to-char-backward ""))
(require 'command-log-mode) (global-command-log-mode) (setq clm/log-command-exceptions* '(mozc-handle-event self-insert-command))
(require 'elfeed) (setq elfeed-feeds '(("https://www.sanityinc.com/feed.xml" emacs) ("https://sachachua.com/blog/category/weekly/feed/" emacs) ("http://pragmaticemacs.com/feed/" emacs) ("https://techracho.bpsinc.jp/feed" ruby rails) ("https://cprss.s3.amazonaws.com/rubyweekly.com.xml" ruby) ("http://b.hatena.ne.jp/t-wada/rss" test) ("https://efcl.info/feed/" javascript) ("https://api.syosetu.com/writernovel/235132.Atom" novel) ("https://anchor.fm/s/7cd923f4/podcast/rss" podcast) ("https://hackerstations.com/index.xml" programmer) ("https://medium.com/feed/a-journey-with-go" go) ("https://dev.to/feed/go" go) ("https://go.dev/blog/feed.atom?format=xml" go) ("https://hashnode.com/n/go/rss" go) ("https://mattn.kaoriya.net/index.rss" go) ("https://systemcrafters.net/rss/news.xml" systemcrafters) ("http://benedict.co.jp/feed/" benedict) ("https://github.com/golang/go/releases.atom" go release) ("https://github.com/moby/moby/releases.atom" docker release) ("https://github.com/emacs-mirror/emacs/releases.atom" emacs release) ("https://zenn.dev/hsaki/feed" go) ("https://zenn.dev/topics/go/feed" go) ("https://qiita.com/tenntenn/feed" go) ("https://qiita.com/tags/go/feed" go) ("https://qiita.com/talgs/emacs/feed" emacs) ("https://www.rfc-editor.org/rfcrss.xml" rfc) )) (setq elfeed-search-title-max-width 120) ;; default-browser (setq browse-url-browser-function 'browse-url-generic browse-url-generic-program "google-chrome")
;; 青 (defface elfeed-face-tag-go '((t :foreground "#28f")) "go tag face in Elfeed.") (push '(go elfeed-face-tag-go) elfeed-search-face-alist) ;; 濃青 (defface elfeed-face-tag-docker '((t :foreground "#46d")) "docker tag face in Elfeed.") (push '(docker elfeed-face-tag-docker) elfeed-search-face-alist) ;; 赤 (defface elfeed-face-tag-ruby '((t :foreground "#d12e59")) "ruby tag face in Elfeed.") (push '(ruby elfeed-face-tag-ruby) elfeed-search-face-alist) ;; 紫 (defface elfeed-face-tag-emacs '((t :foreground "#9933ff")) "emacs tag face in Elfeed.") (push '(emacs elfeed-face-tag-emacs) elfeed-search-face-alist) ;; 黄緑 (defface elfeed-face-tag-systemcrafters '((t :foreground "#9933ff")) "systemcrafters tag face in Elfeed.") (push '(systemcrafters elfeed-face-tag-systemcrafters) elfeed-search-face-alist) ;; 緑 (defface elfeed-face-tag-rfc '((t :foreground "#008000")) "rfc tag face in Elfeed.") (push '(rfc elfeed-face-tag-rfc) elfeed-search-face-alist)
(require 'google-this) (google-this-mode 1) (setq google-this-location-suffix "co.jp")
(require 'define-word) (global-set-key (kbd "<end>") 'define-word-at-point)
;; 改行するようにする (defun shr-insert-document--for-eww (&rest them) (let ((shr-width 70)) (apply them))) (defun eww-display-html--fill-column (&rest them) (advice-add 'shr-insert-document :around 'shr-insert-document--for-eww) (unwind-protect (apply them) (advice-remove 'shr-insert-document 'shr-insert-document--for-eww))) (advice-add 'eww-display-html :around 'eww-display-html--fill-column) ;; 色設定 (defvar eww-disable-colorize t) (defun shr-colorize-region--disable (orig start end fg &optional bg &rest _) (unless eww-disable-colorize (funcall orig start end fg))) (advice-add 'shr-colorize-region :around 'shr-colorize-region--disable) (advice-add 'eww-colorize-region :around 'shr-colorize-region--disable) (defun eww-disable-color () "eww で文字色を反映させない" (interactive) (setq-local eww-disable-colorize t) (eww-reload)) (defun eww-enable-color () "eww で文字色を反映させる" (interactive) (setq-local eww-disable-colorize nil) (eww-reload)) ;; デフォルトエンジン (setq eww-search-prefix "https://www.google.co.jp/search?q=") (defun eww-tag-pre (dom) (let ((shr-folding-mode 'none) (shr-current-font 'default)) (shr-ensure-newline) (insert (eww-fontify-pre dom)) (shr-ensure-newline))) (defun eww-fontify-pre (dom) (with-temp-buffer (shr-generic dom) (let ((mode (eww-buffer-auto-detect-mode))) (when mode (eww-fontify-buffer mode))) (buffer-string))) (defun eww-fontify-buffer (mode) (delay-mode-hooks (funcall mode)) (font-lock-default-function mode) (font-lock-default-fontify-region (point-min) (point-max) nil)) (defun eww-buffer-auto-detect-mode () (let* ((map '((ada ada-mode) (awk awk-mode) (c c-mode) (cpp c++-mode) (clojure clojure-mode lisp-mode) (csharp csharp-mode java-mode) (css css-mode) (delphi delphi-mode) (emacslisp emacs-lisp-mode) (erlang erlang-mode) (fortran fortran-mode) (fsharp fsharp-mode) (go go-mode) (groovy groovy-mode) (haskell haskell-mode) (html html-mode) (java java-mode) (javascript javascript-mode) (json json-mode javascript-mode) (latex latex-mode) (lisp lisp-mode) (lua lua-mode) (matlab matlab-mode octave-mode) (objc objc-mode c-mode) (perl perl-mode) (php php-mode) (prolog prolog-mode) (python python-mode) (r r-mode) (ruby ruby-mode) (rust rust-mode) (scala scala-mode) (shell shell-script-mode) (smalltalk smalltalk-mode) (sql sql-mode) (swift swift-mode) (visualbasic visual-basic-mode) (xml sgml-mode))) (language (language-detection-string (buffer-substring-no-properties (point-min) (point-max)))) (modes (cdr (assoc language map))) (mode (cl-loop for mode in modes when (fboundp mode) return mode))) (message (format "%s" language)) (when (fboundp mode) mode))) (setq shr-external-rendering-functions '((pre . eww-tag-pre)))
(flycheck-define-checker textlint "A linter for Markdown." :command ("textlint" "--format" "unix" source) ;; :command ("docker" "run" "-v" "/home/silver/roam:/home/silver/roam" "--rm" "ghcr.io/kijimad/roam_textlint" "textlint" "-c" "/home/silver/roam/.textlintrc" "--format" "unix" source) :error-patterns ((warning line-start (file-name) ":" line ":" column ": " (id (one-or-more (not (any " ")))) (message (one-or-more not-newline) (zero-or-more "\n" (any " ") (one-or-more not-newline))) line-end)) :modes (text-mode markdown-mode gfm-mode org-mode)) (add-hook 'markdown-mode-hook '(lambda () (add-node-modules-path) (setq flycheck-checker 'textlint) (current-word-highlight-mode) (flycheck-mode 1))) (add-hook 'org-mode-hook '(lambda () (add-node-modules-path) (setq flycheck-checker 'textlint) (flycheck-mode 1)))
(global-set-key (kbd "C-M-%") 'vr/query-replace)
(setq git-link-default-branch "main") (setq git-link-use-commit t)
(global-undo-tree-mode)
(setq undo-tree-auto-save-history nil)
(setq eradio-channels '(("def con - soma fm" . "https://somafm.com/defcon256.pls") ("metal - soma fm" . "https://somafm.com/metal130.pls") ("cyberia - lainon" . "https://lainon.life/radio/cyberia.ogg.m3u") ("cafe - lainon" . "https://lainon.life/radio/cafe.ogg.m3u") ("ambient - HBR1.com" . "http://ubuntu.hbr1.com:19800/ambient.ogg") ("ambient - RADIO ESTILO LEBLON" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://us4.internet-radio.com:8193/listen.pls&t=.m3u") ("ambient - Pink Noise Radio" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://uk1.internet-radio.com:8004/listen.pls&t=.m3u") ("ambient - Deeply Beautiful Chillout Music - A Heavenly World of Sound" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://uk2.internet-radio.com:31491/listen.pls&t=.m3u") ("ambient - Chill Lounge Florida" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://us5.internet-radio.com:8283/listen.pls&t=.m3u") ("ambient - PARTY VIBE RADIO : AMBIENT" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://www.partyviberadio.com:8056/listen.pls?sid=1&t=.m3u") ("healing - Healing Music Radio - The music of Peter Edwards" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://us3.internet-radio.com:8169/live.m3u&t=.m3u") ("ambient - Real World Sounds" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://uk5.internet-radio.com:8260/listen.pls&t=.m3u") ("meditation - SilentZazen" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://uk5.internet-radio.com:8167/live.m3u&t=.m3u") ("meditation - Zero Beat Zone (MRG.fm)" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://62.149.196.16:8800/listen.pls?sid=1&t=.m3u") ("meditation - Meditation Radio" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://213.239.218.99:7241/listen.pls?sid=1&t=.m3u") ("ambient - AmbientRadio (MRG.fm)" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://62.149.196.16:8888/listen.pls?sid=1&t=.m3u") ("jungle - Konflict Radio" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://uk3.internet-radio.com:8192/live.m3u&t=.m3u") ("jungle - Future Pressure Radio" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://uk3.internet-radio.com:8108/listen.pls&t=.m3u") ("jungle - PARTY VIBE RADIO : JUNGLE" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://www.partyviberadio.com:8004/listen.pls?sid=2&t=.m3u") ("jazz - Smooth Jazz Florida" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://us4.internet-radio.com:8266/listen.pls&t=.m3u") ("rock - Classic Rock Florida HD" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://us4.internet-radio.com:8258/listen.pls&t=.m3u") ("dance - Dance UK Radio danceradiouk" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://uk2.internet-radio.com:8024/listen.pls&t=.m3u") ("rock - Majestic Jukebox Radio #HIGH QUALITY SOUND" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://uk3.internet-radio.com:8405/live.m3u&t=.m3u") ("ambient - LIFE CHILL MUSIC" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://aska.ru-hoster.com:8053/autodj.m3u&t=.m3u") ("dance - PulseEDM Dance Music Radio" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://pulseedm.cdnstream1.com:8124/1373_128.m3u&t=.m3u") ("piano - Matt Johnson Radio" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://us2.internet-radio.com:8046/listen.pls&t=.m3u") ("piano - Music Lake - Relaxation Music, Meditation, Focus, Chill, Nature Sounds" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://104.251.118.50:8626/listen.pls?sid=1&t=.m3u") ("piano - Bru Zane Classical Radio - Rediscovering French Romantic Music" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://116.202.241.212:7001/listen.pls?sid=1&t=.m3u") ("piano - CALMRADIO.COM - Most Beautiful Piano Ever" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://209.58.147.84:19991/listen.pls?sid=1&t=.m3u") ("piano - CALMRADIO.COM - Light Jazz Piano" . "https://www.internet-radio.com/servers/tools/playlistgenerator/?u=http://23.82.11.88:10800/listen.pls?sid=1&t=.m3u") ))
(setq toe-highscore-file "~/.emacs.d/games/.toe-scores")
(setq create-link-default-format 'create-link-format-org)
(require 'lispxmp) (define-key emacs-lisp-mode-map (kbd "C-<return>") 'lispxmp)
(require 'graphql-mode) (require 'ob-graphql)
Rails
(require 'projectile-rails) (projectile-rails-global-mode) (add-hook 'projectile-mode-hook 'projectile-rails-on)
(require 'rspec-mode) ;; Rspecの実行結果をスクロールして出力する (setq compilation-scroll-output t) ;; Dockerのときの設定。プロジェクトごとに設定したいが… (setq rspec-use-docker-when-possible 1) (setq rspec-docker-container "rails") (setq rspec-docker-command "docker-compose -f docker-compose.yml -f docker-compose-app.yml -f docker-compose-app.override.yml exec") (setq rspec-docker-cwd "")
(defun rspec-runner () "Return command line to run rspec." (let ((bundle-command (if (rspec-bundle-p) "RAILS_ENV=test bundle exec " "")) (zeus-command (if (rspec-zeus-p) "zeus " nil)) (spring-command (if (rspec-spring-p) "spring " nil))) (concat (or zeus-command spring-command bundle-command) (if (rspec-rake-p) (concat rspec-rake-command " spec") rspec-spec-command))))
(setq rspec-use-spring-when-possible t) (defun rspec-spring-p () (and rspec-use-spring-when-possible (stringp (executable-find "spring"))))
(require 'rubocop) (add-hook 'ruby-mode-hook 'rubocop-mode) (add-hook 'ruby-mode-hook '(lambda () (setq flycheck-checker 'ruby-rubocop))) ;; See: https://qiita.com/watson1978/items/debafdfc49511fb173e9 ;; 独自に checker を定義する(お好みで) (flycheck-define-checker ruby-rubocop "A Ruby syntax and style checker using the RuboCop tool." :command ("rubocop" "--format" "emacs" (config-file "--config" flycheck-rubocoprc) source) :error-patterns ((warning line-start (file-name) ":" line ":" column ": " (or "C" "W") ": " (message) line-end) (error line-start (file-name) ":" line ":" column ": " (or "E" "F") ": " (message) line-end)) :modes (ruby-mode motion-mode)) (setq flycheck-ruby-rubocop-executable "bundle exec rubocop")
(when (require 'rinari nil 'noerror) (require 'rinari) (add-hook 'ruby-mode-hook 'rinari-minor-mode)) (when (require 'rinari nil 'noerror) (require 'rspec-mode) (eval-after-load 'rspec-mode '(rspec-install-snippets)))
(require 'ruby-electric) (add-hook 'ruby-mode-hook '(lambda () (ruby-electric-mode t)))
(require 'inf-ruby) (setq inf-ruby-default-implementation "pry") (setq inf-ruby-eval-binding "Pry.toplevel_binding") ;; riなどのエスケープシーケンスを処理し、色付けする (add-hook 'inf-ruby-mode-hook 'ansi-color-for-comint-mode-on)
(unless (package-installed-p 'slim-mode) (package-refresh-contents) (package-install 'slim-mode)) (add-to-list 'auto-mode-alist '("\\.slim?\\'" . slim-mode))
(setq ruby-insert-encoding-magic-comment nil)
(defcustom ruby-block-delay 0 "*Time in seconds to delay before showing a matching paren." :type 'number :group 'ruby-block)
(require 'rcodetools) (define-key ruby-mode-map (kbd "C-<return>") 'xmp)
Go
goの設定。
(require 'go-mode) (require 'ob-go)
(use-package dap-mode :after lsp-mode :hook (lsp-mode . dap-mode) (lsp-mode . dap-ui-mode) :config (dap-mode 1) (require 'dap-hydra) (require 'dap-dlv-go)) (setq dap-print-io t) (setq lsp-gopls-server-path "~/go/bin/gopls") (setq dap-dlv-go-delve-path "~/go/bin/dlv")
(require 'go-eldoc) (add-hook 'go-mode-hook 'go-eldoc-setup)
(setq gofmt-command "goimports") (add-hook 'before-save-hook 'gofmt-before-save)
(use-package ob-go-asm :straight (:host github :repo "kijimaD/ob-go-asm"))
Haskell
haskellの設定。
(add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode) (add-hook 'haskell-mode-hook 'turn-on-haskell-indent) (custom-set-variables '(haskell-indent-after-keywords (quote (("where" 4 0) ("of" 4) ("do" 4) ("mdo" 4) ("rec" 4) ("in" 4 0) ("{" 4) "if" "then" "else" "let"))) '(haskell-indent-offset 4) '(haskell-indent-spaces 4))
Yaml
(add-to-list 'auto-mode-alist '("\\.ya?ml$" . yaml-mode))
(require 'origami) (define-minor-mode origami-view-mode "TABにorigamiの折畳みを割り当てる" nil "折紙" '(("\C-i" . origami-cycle)) (or origami-mode (origami-mode 1))) (defun origami-cycle (recursive) "origamiの機能をorg風にまとめる" (interactive "P") (call-interactively (if recursive 'origami-toggle-all-nodes 'origami-toggle-node))) (defun yaml-mode-hook--origami () (when (eq major-mode 'yaml-mode) (origami-view-mode))) (add-hook 'yaml-mode-hook 'yaml-mode-hook--origami)
Web
web-modeはhtmlライクな複数の言語に対応するモード。
;; web-mode (require 'web-mode) (add-to-list 'auto-mode-alist '("\\.js[x]?$" . web-mode));; js + jsx (add-to-list 'auto-mode-alist '("\\.tsx$" . web-mode)) (add-to-list 'auto-mode-alist '("\\.phtml\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.[gj]sp\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.as[cp]x\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.erb\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.mustache\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode)) (add-to-list 'auto-mode-alist '("\\.html\\'" . web-mode)) (setq web-mode-engines-alist '(("php" . "\\.phtml\\'") ("blade" . "\\.blade\\."))) ;; JS+JSX設定 ================ ;; コメントアウトの設定 (add-hook 'web-mode-hook '(lambda () (add-to-list 'web-mode-comment-formats '("jsx" . "//" )))) ;; .js でも JSX 編集モードに (setq web-mode-content-types-alist '(("jsx" . "\\.js[x]?\\'"))) ;; JSシンタックスチェック ================ ;; ESlint (eval-after-load 'flycheck '(custom-set-variables '(flycheck-disabled-checkers '(javascript-jshint javascript-jscs)) )) ;; eslint 用の linter を登録 (flycheck-add-mode 'javascript-eslint 'web-mode) ;; 作業している project の node-module をみて、適切に ;; linter の設定を読み込む (eval-after-load 'web-mode '(progn (add-hook 'web-mode-hook #'add-node-modules-path) (add-hook 'web-mode-hook #'prettier-js-mode))) (eval-after-load 'web-mode '(add-hook 'rjsx-mode-hook #'add-node-modules-path)) (add-hook 'web-mode-hook 'flycheck-mode) (add-hook 'rjsx-mode-hook 'flycheck-mode) ;; 実行: M-x eslint-fix-file (defun eslint-fix-file () (interactive) (call-process-shell-command (mapconcat 'shell-quote-argument (list "eslint" "--fix" (buffer-file-name)) " ") nil 0)) ;; 実行後、buffer を revert する ;; 実行: M-x eslint-fix-file-and-revert (defun eslint-fix-file-and-revert () (interactive) (eslint-fix-file) (revert-buffer t t)) ;; インデント等調整 ================ (defun my-web-mode-hook () "Hooks for Web mode." ;; (setq web-mode-attr-indent-offset 0) ;; (setq web-mode-markup-indent-offset 0) ;; (setq web-mode-css-indent-offset 0) ;; (setq web-mode-code-indent-offset 0) ;; (setq web-mode-sql-indent-offset 0) ;; (setq sql-indent-offset 0) (setq indent-tabs-mode nil) (setq tab-width 2) (setq json-reformat:indent-width 2) (setq web-mode-attr-indent-offset nil) (setq web-mode-enable-auto-closing t) (setq web-mode-enable-auto-pairing t) (setq web-mode-auto-close-style 2) (setq web-mode-tag-auto-close-style 2)) (add-hook 'web-mode-hook 'my-web-mode-hook) ;; CSS ================ (setq css-indent-offset 2) ;; SQL ================ (add-hook 'ejc-sql-minor-mode-hook (lambda () (ejc-eldoc-setup))) ;; コマンドを大文字にする (add-hook 'sql-mode-hook 'sqlup-mode) (add-hook 'sql-interactive-mode-hook 'sqlup-mode) (global-set-key (kbd "C-c u") 'sqlup-capitalize-keywords-in-region) ;; 結果を折り返さないようにする (add-hook 'sql-interactive-mode-hook '(lambda() (setq truncate-lines nil truncate-partial-width-windows t))) (setq erc-server "irc.libera.chat" erc-nick "kijimad" erc-user-full-name "Kijima Daigo" erc-track-shorten-start 8 erc-autojoin-channels-alist '(("irc-libera.chat" "#systemcrafters" "#emacs")) erc-kill-buffer-on-part t erc-auto-query 'bufy) ;; Typescript ================ (require 'typescript-mode) (add-to-list 'auto-mode-alist '("\\.ts\\'" . typescript-mode))
LSP
lsp-modeはLSPを使えるようにするパッケージ。
(setq lsp-verify-signature nil)
(use-package flycheck :init (global-flycheck-mode)) (use-package lsp-mode :custom (lsp-completion-provider :none) (lsp-prefer-flymake nil) (lsp-print-io nil) (lsp-trace nil) (lsp-print-performance nil) (lsp-auto-guess-root t) (lsp-document-sync-method 'incremental) (lsp-response-timeout 5) :init (defun my/lsp-mode-setup-completion () (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults)) '(orderless))) ;; Configure orderless :hook (scala-mode . lsp) (clojure-mode . lsp) (c-mode . lsp) (c++-mode . lsp) (rust-mode . lsp) (go-mode . lsp) (lsp-mode . lsp-lens-mode) (lsp-mode . lsp-completion-mode) (lsp-mode . lsp-ui-mode) (lsp-completion-mode . my/lsp-mode-setup-completion) :config ;; Uncomment following section if you would like to tune lsp-mode performance according to ;; https://emacs-lsp.github.io/lsp-mode/page/performance/ (setq gc-cons-threshold 100000000) ;; 100mb (setq read-process-output-max (* 1024 1024 10)) ;; 10mb (setq lsp-idle-delay 0.500) (setq lsp-log-io nil) )
;; (use-package scala-mode ;; :interpreter ;; ("scala" . scala-mode)) ;; ;; Enable sbt mode for executing sbt commands ;; (use-package sbt-mode ;; :commands sbt-start sbt-command ;; :config ;; ;; WORKAROUND: https://github.com/ensime/emacs-sbt-mode/issues/31 ;; ;; allows using SPACE when in the minibuffer ;; (substitute-key-definition ;; 'minibuffer-complete-word ;; 'self-insert-command ;; minibuffer-local-completion-map) ;; ;; sbt-supershell kills sbt-mode: https://github.com/hvesalai/emacs-sbt-mode/issues/152 ;; (setq sbt:program-options '("-Dsbt.supershell=false")) ;; ) ;; (use-package lsp-metals ;; :ensure t ;; :custom ;; ;; Metals claims to support range formatting by default but it supports range ;; ;; formatting of multiline strings only. You might want to disable it so that ;; ;; emacs can use indentation provided by scala-mode. ;; (lsp-metals-server-args '("-J-Dmetals.allow-multiline-string-formatting=off")) ;; :hook (scala-mode . lsp))
使ってない。
(use-package lsp-ui :custom (lsp-ui-doc-enable t) (lsp-ui-doc-header t) (lsp-ui-doc-include-signature t) (lsp-ui-doc-max-width 150) (lsp-ui-doc-max-height 30) (lsp-ui-peek-enable t))
(use-package yasnippet)
(use-package posframe ;; Posframe is a pop-up tool that must be manually installed for dap-mode ) (use-package dap-ui :config (dap-ui-mode 1))
corfu
corfuはシンプルな補完を提供するパッケージ。
(require 'corfu) (global-corfu-mode)
(setq corfu-auto t) (setq corfu-auto-prefix 3) (setq corfu-count 15) (setq corfu-cycle t) (setq corfu-preselect-first nil) ;; 自動的に最初の候補を選択する (setq corfu-preselect 'prompt) (setq corfu-quit-at-boundary t) ;; スペースを入れるとquit (setq corfu-quit-no-match t)
(setq completion-cycle-threshold 3) (defun corfu-beginning-of-prompt () "Move to beginning of completion input." (interactive) (corfu--goto -1) (goto-char (car completion-in-region--data))) (defun corfu-end-of-prompt () "Move to end of completion input." (interactive) (corfu--goto -1) (goto-char (cadr completion-in-region--data))) (define-key corfu-map [remap move-beginning-of-line] #'corfu-beginning-of-prompt) (define-key corfu-map [remap move-end-of-line] #'corfu-end-of-prompt)
vertico
verticoは検索UIを提供するパッケージ。
(use-package vertico-repeat :after vertico :hook (minibuffer-setup . vertico-repeat-save))
(require 'vertico) (vertico-mode) (setq vertico-count 20) (require 'vertico-directory) (define-key vertico-map (kbd "C-l") #'vertico-directory-up) (define-key vertico-map "\r" #'vertico-directory-enter) ;; enter dired (define-key vertico-map "\d" #'vertico-directory-delete-char) (require 'marginalia) (marginalia-mode +1) ;; marginalia-annotatorsをサイクルする (define-key minibuffer-local-map (kbd "C-M-a") #'marginalia-cycle) (require 'orderless) (setq completion-styles '(orderless partial-completion)) (setq completion-category-defaults nil) (setq completion-category-overrides nil) (orderless-define-completion-style orderless+initialism (orderless-matching-styles '(orderless-initialism ;;一番最初にinitializm orderless-literal ;;次にリテラルマッチ orderless-regexp))) ;; (setq completion-category-defaults nil) (setq completion-category-overrides '((eglot (styles orderless+initialism)) (command (styles orderless+initialism)) (symbol (styles orderless+initialism)) (variable (styles orderless+initialism)))) (setq orderless-component-separator #'orderless-escapable-split-on-space) (require 'cape) (add-to-list 'completion-at-point-functions #'cape-file) (add-to-list 'completion-at-point-functions #'cape-tex) (add-to-list 'completion-at-point-functions #'cape-dabbrev) (add-to-list 'completion-at-point-functions #'cape-keyword) (add-to-list 'completion-at-point-functions #'cape-abbrev) (add-to-list 'completion-at-point-functions #'cape-ispell) (add-to-list 'completion-at-point-functions #'cape-symbol)
;; EmacsのSVG対応コンパイルが必要 (require 'kind-icon) (setq kind-icon-default-face 'corfu-default) ;; If 4k, big size icon displayed. (add-to-list 'corfu-margin-formatters #'kind-icon-margin-formatter) (pop corfu-margin-formatters) ;; Available commands ;; affe-grep: Filters the content of all text files in the current directory ;; affe-find: Filters the file paths of all files in the current directory (require 'affe) (consult-customize affe-grep :preview-key (kbd "M-.")) (defvar affe-orderless-regexp "") (defun affe-orderless-regexp-compiler (input _type) (setq affe-orderless-regexp (orderless-pattern-compiler input)) (cons affe-orderless-regexp (lambda (str) (orderless--highlight affe-orderless-regexp str)))) (setq affe-regexp-compiler #'affe-orderless-regexp-compiler)
(global-set-key (kbd "C-x C-b") 'consult-buffer) (global-set-key (kbd "C-x C-u") 'vertico-repeat) (global-set-key (kbd "C-x C-g") 'consult-git-grep) (global-set-key (kbd "M-y") 'consult-yank-pop) (global-set-key (kbd "M-i") 'consult-line)
(add-hook 'after-init-hook '(lambda () (ido-mode 0) (ido-everywhere 0)))
(use-package all-the-icons-completion :straight t :hook (marginalia-mode . all-the-icons-completion-marginalia-setup) :init (all-the-icons-completion-mode +1))
emacs Lisp
rispy
rispyはリストの操作をやりやすくするパッケージ。
(require 'lispy) (add-hook 'emacs-lisp-mode-hook (lambda () (lispy-mode 1)))
(define-key lispy-mode-map (kbd "M-<right>") 'next-buffer) (define-key lispy-mode-map (kbd "M-<left>") 'previous-buffer) (define-key lispy-mode-map (kbd "M-i") 'swiper-thing-at-point)
eldoc
eldocは関数ドキュメントを表示するパッケージ。
(with-eval-after-load "eldoc" (defun ad:eldoc-message (f &optional string) (unless (active-minibuffer-window) (funcall f string))) (advice-add 'eldoc-message :around #'ad:eldoc-message))
eshell
eshellはEmacs Lispで実装されたシェル。
(defun efs/configure-eshell () ;; Save command history when commands are entered (add-hook 'eshell-pre-command-hook 'eshell-save-some-history) ;; Truncate buffer for performance (add-to-list 'eshell-output-filter-functions 'eshell-truncate-buffer) ;; Bind some useful keys for evil-mode ;; (define-key eshell-mode-map (kbd "M-r") 'helm-eshell-history) (setq eshell-history-size 10000 eshell-buffer-maximum-lines 10000 eshell-hist-ignoredups t eshell-scroll-to-bottom-on-input t eshell-git-prompt-use-theme 'multiline eshell-toggle-height-fraction 2 eshell-toggle-use-projectile-root t)) (add-hook 'eshell-first-time-mode-hook 'efs/configure-eshell)
(global-set-key (kbd "C-M-;") 'eshell-toggle)
(add-hook 'eshell-first-time-mode-hook 'esh-autosuggest-mode)
(setq esh-autosuggest-delay 0.5)
Vterm
vtermはCで実装されたシェル。
(when window-system (require 'vterm) (setq term-prompt-regexp "^[^#$%>\n]*[#$%>] *") (setq vterm-toggle-scope 'project) (setq vterm-toggle-project-root t) (setq vterm-max-scrollback 10000) ;; toggle (global-set-key [f9] 'vterm-toggle) (global-set-key (kbd "C-M-:") 'vterm-toggle) (global-set-key [C-f9] 'vterm-toggle-cd) (setq vterm-toggle-fullscreen-p nil) (add-to-list 'display-buffer-alist '((lambda(bufname _) (with-current-buffer bufname (or (equal major-mode 'vterm-mode) (string-prefix-p vterm-buffer-name bufname)))) (display-buffer-reuse-window display-buffer-at-bottom) ;;(display-buffer-reuse-window display-buffer-in-direction) ;;display-buffer-in-direction/direction/dedicated is added in emacs27 ;;(direction . bottom) ;;(dedicated . t) ;dedicated is supported in emacs27 (reusable-frames . visible) (window-height . 0.3))))
Theme
いい感じのテーマを設定する。割と白いテーマと黒いテーマを切り替えるのですぐ切り替えられるようにする。
(require 'doom-themes) (doom-themes-org-config) (setq custom-safe-themes t) (setq-default custom-enabled-themes '(doom-tokyo-night))
doom themeはモダンなテーマ集。
- ダーク系
- doom-vibrant
- spacemacs-dark
- doom-dracula
- modus-vivendi
- leuven-dark
- ライト系
- leuven
- doom-acario-light
- doom-homage-white
- modus-operandi
(defun reapply-themes () "Forcibly load the themes listed in `custom-enabled-themes'." (dolist (theme custom-enabled-themes) (unless (custom-theme-p theme) (load-theme theme))) (custom-set-variables `(custom-enabled-themes (quote ,custom-enabled-themes))) (efs/org-font-setup) ;; (kd/set-modus-face) ) (add-hook 'after-init-hook 'reapply-themes)
テーマ適用を最後に実行しないと、設定が上書きされることがあるため。
(doom-modeline-mode) ;; 表示項目の設定 (setq doom-modeline-buffer-file-name-style 'truncate-with-project) (setq doom-modeline-major-mode-icon t) (setq doom-modeline-minor-modes nil) (setq doom-modeline-buffer-encoding nil) (line-number-mode) (column-number-mode) (doom-modeline-def-modeline 'my-simple-line '(bar matches buffer-info remote-host input-method major-mode process buffer-position) '(misc-info vcs checker)) ;; 縦調整 (defun my-doom-modeline--font-height () (- (frame-char-height) 20)) (advice-add #'doom-modeline--font-height :override #'my-doom-modeline--font-height) (setq doom-modeline-height 20) (defun setup-custom-doom-modeline () (doom-modeline-set-modeline 'my-simple-line 'default)) (add-hook 'doom-modeline-mode-hook 'setup-custom-doom-modeline) (setup-custom-doom-modeline)
(defun kd/set-modus-face () (setq modus-themes-slanted-constructs t modus-themes-bold-constructs t modus-themes-no-mixed-fonts t modus-themes-subtle-line-numbers t modus-themes-mode-line '(moody borderless) modus-themes-syntax 'faint modus-themes-paren-match 'intense-bold modus-themes-region 'bg-only modus-themes-diffs 'deuteranopia modus-themes-org-blocks 'gray-background modus-themes-variable-pitch-ui t modus-themes-variable-pitch-headings t modus-themes-scale-headings t modus-themes-scale-1 1.1 modus-themes-scale-2 1.15 modus-themes-scale-3 1.21 modus-themes-scale-4 1.27 modus-themes-scale-title 1.33) (set-face-foreground 'vertical-border "gray") (set-face-attribute 'mode-line nil :background nil :overline "black" :underline nil :box nil) (set-face-attribute 'mode-line-inactive nil :background "white" :overline "gray" :underline nil :box nil) (window-divider-mode 0))
(setq my-hidden-minor-modes '( abbrev-mode auto-highlight-symbol-mode auto-revert-mode back-button-mode beacon-mode command-log-mode ctags-auto-update-mode eldoc-mode flycheck-mode flyspell-mode global-whitespace-mode google-this-mode highlight-indent-guides-mode magit-auto-revert-mode projectile-mode projectile-rails-mode rinari-minor-mode rubocop-mode ruby-electric-mode undo-tree-mode which-key-mode yas-minor-mode )) (mapc (lambda (mode) (setq minor-mode-alist (cons (list mode "") (assq-delete-all mode minor-mode-alist)))) my-hidden-minor-modes) (setq minor-mode-alist nil)
describe-minor-mode-from-indicator で調べられる。
EXWM
EXWMはEmacs上で動くウィンドウマネージャ。
(require 'exwm) (require 'exwm-config)
(setq exwm-replace t)
(setq exwm-layout-show-all-buffers t)
(setq mouse-autoselect-window nil
focus-follows-mouse t
exwm-workspace-warp-cursor t
exwm-workspace-number 5)
(add-hook 'exwm-update-class-hook (lambda () (exwm-workspace-rename-buffer exwm-class-name))) (add-hook 'exwm-update-title-hook (lambda () (pcase exwm-class-name ("qutebrowser" (exwm-workspace-rename-buffer (format "Qutebrowser: %s" exwm-title))) ("chrome" (exwm-workspace-rename-buffer (format "Chrome: %s" exwm-title))))))
(defun kd/set-init () "Window Manager関係の各種プログラムを起動する." (interactive) (kd/set-background) (call-process-shell-command "shepherd") (call-process-shell-command "~/dotfiles/.config/polybar/launch.sh") (exwm-workspace-switch-create 0) (start-process-shell-command "google-chrome" nil "google-chrome") (sleep-for 2) (start-process-shell-command "spotify" nil "spotify") (sleep-for 1) (persp-switch "1") (delete-other-windows) (if (file-exists-p org-journal-dir) (org-journal-new-entry nil)) (vterm-toggle) (vterm-toggle) (persp-switch "2") (find-file "~/roam") (vterm-toggle) (vterm-toggle) (org-agenda nil "z") (persp-switch "3") (split-window-right) (switch-to-buffer "Google-chrome") (persp-switch "4") (switch-to-buffer "Google-chrome") (vterm-toggle) (vterm-toggle) (persp-switch "5") (find-file "~/dotfiles") (vterm-toggle) (vterm-toggle) (magit-status) (persp-switch "6") (find-file "~/.emacs.d/conf") (vterm-toggle) (vterm-toggle) (magit-status) (persp-switch "7") (find-file "~/ProjectOrg") (persp-switch "8") (find-file "~/Project") (persp-switch "9") (elfeed) (exwm-workspace-switch-create 1) (persp-switch "1") (persp-switch "2") (find-file "~/roam") (org-agenda nil "z") (persp-switch "4") (switch-to-buffer "Google-chrome") (persp-switch "8") (find-file "~/Project") (exwm-workspace-switch-create 2) (switch-to-buffer "Spotify") (exwm-workspace-switch-create 0) (persp-switch "4") (message "settings done!"))
(defun kd/set-background () "背景をセットする." (interactive) (start-process-shell-command "compton" nil "compton --config ~/dotfiles/.config/compton/compton.conf") (start-process-shell-command "fehbg" nil "~/dotfiles/.fehbg"))
(defvar kd/last-workspace-index 0) (defun kd/exwm-workspace-switch-last () (interactive) (let ((old kd/last-workspace-index)) (setq kd/last-workspace-index exwm-workspace-current-index) (exwm-workspace-switch old)))
マルチディスプレイ時に簡易にトグルで切り替える用。ワークスペース切り替え時のbefore hookがないので、他のコマンドで切り替えたときに対応してない。
(define-key exwm-mode-map (kbd "C-M-:") 'vterm-toggle) (define-key exwm-mode-map (kbd "C-M-<right>") 'persp-next) (define-key exwm-mode-map (kbd "C-M-<left>") 'persp-prev) (define-key exwm-mode-map (kbd "<henkan>") 'pretty-hydra-henkan/body)
(when window-system (progn (exwm-config-example) ;; (kd/set-init) ))
(require 'exwm-randr) (setq exwm-randr-workspace-output-plist '(1 "HDMI-1")) (add-hook 'exwm-randr-screen-change-hook (lambda () (start-process-shell-command "xrandr" nil "xrandr --output HDMI-1 --mode 1920x1080 --right-of eDP-1 --auto"))) (exwm-enable) (exwm-randr-enable)
randr関係の修正をしたときは、 (exwm-randr-refresh)
を実行して反映する。例えば、画面と対応したワークスペースを変更したとき。
Polybar
polybarは柔軟にカスタマイズできるメニューバーを表示するソフトウェア。polybarとの連携を記載する。
(defvar kd/polybar-process nil "Holds the process of the running Polybar instance, if any")
(defun kd/start-panel () (interactive) (kd/kill-panel) (setq kd/polybar-process (start-process-shell-command "polybar" nil "~/dotfiles/.config/polybar/launch.sh")))
(defun kd/kill-panel () (interactive) (when kd/polybar-process (ignore-errors (kill-process kd/polybar-process))) (setq kd/polybar-process nil))
(defun kd/polybar-exwm-workspace () (pcase exwm-workspace-current-index (0 "%{F#797D7F}Work%{F-} Home") (1 "Work %{F#797D7F}Home%{F-}") (2 "") (3 "") (4 "") (9 ""))) (defun kd/send-polybar-exwm-workspace () (kd/send-polybar-hook "exwm-workspace" 1)) (defun kd/send-polybar-hook (module-name hook-index) (start-process-shell-command "polybar-msg" nil (format "polybar-msg hook %s %s" module-name hook-index))) (add-hook 'exwm-workspace-switch-hook #'kd/send-polybar-exwm-workspace)
Workspace
1~9のワークスペースを作成し、番号で切り替えられるようにする。
(require 'perspective) (setq persp-initial-frame-name "1") (setq persp-modestring-dividers '("" "" " ")) (persp-mode 1)
(mapc (lambda (i) (persp-switch (int-to-string i))) (number-sequence 0 9)) (persp-switch "1")
Hydra
Hydraはカスタマイズ可能なキー表示を追加するパッケージ。キーバインド空間を制限しつつ、入力のヒントを表示して使いやすくする。
(with-eval-after-load 'pretty-hydra (pretty-hydra-define pretty-hydra-henkan (:color blue :foreign-keys warn :title "Convenient Tools") ("Media" (("<prior>" kd/mint-volume-up "up") ("<next>" kd/mint-volume-down "down") ("<pause>" kd/player-stop "stop") ("<SPC>" eradio-toggle "stop")) "Find" (("a" counsel-apropos "apropos") ("f" consult-find "find") ("p" consult-project-buffer "project-buffer") ("r" consult-register "list register") ("s" consult-register-store "store register")) "Execute" (("d" denote-template "denote-template") ("e" counsel-linux-app "run") ("c" recompile "recompile") ("!" org-pomodoro "start pomodoro") ("n" elfeed "elfeed")) "Git" (("g" git-link) (">" git-gutter+-next-hunk) ("<" git-gutter+-previous-hunk) ("@" git-timemachine)) "Edit" (("q" query-replace "replace") ("y" ivy-yasnippet "yas") ("R" revert-buffer-no-confirm "reload")) "Window" (("l" (lambda nil (interactive) (persp-switch-last)) "Last") ("1" (lambda nil (interactive) (persp-switch (int-to-string 1))) "Journal") ("2" (lambda nil (interactive) (persp-switch (int-to-string 2))) "Roam") ("3" (lambda nil (interactive) (persp-switch (int-to-string 3))) "Browser(Half)") ("4" (lambda nil (interactive) (persp-switch (int-to-string 4))) "Browser(Full)") ("5" (lambda nil (interactive) (persp-switch (int-to-string 5))) "Dotfiles") ("6" (lambda nil (interactive) (persp-switch (int-to-string 6))) "Emacs") ("7" (lambda nil (interactive) (persp-switch (int-to-string 7))) "Sub") ("8" (lambda nil (interactive) (persp-switch (int-to-string 8))) "Main") ("9" (lambda nil (interactive) (persp-switch (int-to-string 9))) "Elfeed") ("0" (lambda nil (interactive) (persp-switch (int-to-string 0))) "Sub")) "Workspace" (("w" (lambda nil (interactive) (kd/exwm-workspace-switch-last)) "Last")))) (define-key global-map (kbd "<henkan>") 'pretty-hydra-henkan/body))
(with-eval-after-load 'pretty-hydra (pretty-hydra-define pretty-hydra-projectile-rails-find (:color blue :foreign-keys warn :title "Projectile Rails") ("Current" (("M" projectile-rails-find-current-model "Current model") ("V" projectile-rails-find-current-view "Current view") ("C" projectile-rails-find-current-controller "Current controller") ("H" projectile-rails-find-current-helper "Current helper") ("P" projectile-rails-find-current-spec "Current spec") ("Z" projectile-rails-find-current-serializer "Current serializer")) "App" (("m" projectile-rails-find-model "Model") ("v" projectile-rails-find-view "View") ("c" projectile-rails-find-controller "Controller") ("h" projectile-rails-find-helper "Helper") ("@" projectile-rails-find-mailer "Mailer") ("y" projectile-rails-find-layout "Layout") ("z" projectile-rails-find-serializer "Serializer")) "Assets" (("j" projectile-rails-find-javascript "Javascript") ("s" projectile-rails-find-stylesheet "CSS")) "Other" (("n" projectile-rails-find-migration "Migration") ("r" projectile-rails-find-rake-task "Rake task") ("i" projectile-rails-find-initializer "Initializer") ("l" projectile-rails-find-lib "Lib") ("p" projectile-rails-find-spec "Spec") ("t" projectile-rails-find-locale "Translation")) "Single Files" (("R" projectile-rails-goto-routes "routes.rb") ("G" projectile-rails-goto-gemfile "Gemfile") ("D" projectile-rails-goto-schema "schema.rb")))))
(global-set-key (kbd "M-SPC") #'major-mode-hydra) (with-eval-after-load 'major-mode-hydra (major-mode-hydra-define emacs-lisp-mode nil ("Eval" (("b" eval-buffer "buffer") ("e" eval-defun "defun")) "REPL" (("I" ielm "ielm")) "Test" (("r" (ert-run-tests-interactively (car ert--selector-history)) "rerun") ("t" ert "prompt") ("T" (ert t) "all") ("F" (ert :failed) "failed")) "Doc" (("f" describe-function "function") ("v" describe-variable "variable") ("i" info-lookup-symbol "info lookup"))))) (with-eval-after-load 'major-mode-hydra (major-mode-hydra-define org-agenda-mode nil ("pomodoro" (("s" org-pomodoro "start org-pomodoro")))))
メジャーモードに対するhydraを設定する。
Display Manager
OS操作の便利関数。
(defun kd/mint-volume-up () "Linux Mintでの音量アップ." (interactive) (start-process-shell-command "volume up" nil "pactl set-sink-volume @DEFAULT_SINK@ +5%")) (defun kd/mint-volume-down () "Linux Mintでの音量ダウン." (interactive) (start-process-shell-command "volume up" nil "pactl set-sink-volume @DEFAULT_SINK@ -5%"))
(defun kd/player-stop () "再生停止" (interactive) (start-process-shell-command "player stop" nil "playerctl stop"))
(defun kd/up-network () "ネットワーク接続" (interactive) (let ((passwd)) (setq passwd (read-passwd "Password? ")) (shell-command (concat "for intf in /sys/class/net/*; do echo " (shell-quote-argument passwd) " | sudo -S ifconfig `basename $intf` up; done")))) (defun kd/down-network () "ネットワーク切断" (interactive) (let ((passwd)) (setq passwd (read-passwd "Password? ")) (shell-command (concat "for intf in /sys/class/net/*; do echo " (shell-quote-argument passwd) " | sudo -S ifconfig `basename $intf` down; done"))))
;; (use-package ej-dict ;; :straight (:host github :repo "kijimaD/ej-dict")) ;; (ej-dict-install-dict)
Helper
その他の便利関数。
(defun my-exchange-point-and-mark () (interactive) (exchange-point-and-mark) (deactivate-mark)) (global-set-key (kbd "C-x C-x") 'my-exchange-point-and-mark)
(global-set-key (kbd "C-c C-k") 'kill-whole-line)
(defun current-path () (interactive) (let ((file-path buffer-file-name) (dir-path default-directory)) (cond (file-path (kill-new (expand-file-name file-path)) (message "Add Kill Ring: %s" (expand-file-name file-path))) (dir-path (kill-new (expand-file-name dir-path)) (message "Add Kill Ring: %s" (expand-file-name dir-path))) (t (error-message-string "Fail to get path name.")))))
(defun my-isearch-done-opposite (&optional nopush edit) "End current search in the opposite side of the match." (interactive) (funcall #'isearch-done nopush edit) (when isearch-other-end (goto-char isearch-other-end)))
(defun my-next-line () (interactive) (next-line) (recenter)) (global-set-key (kbd "<down>") 'my-next-line) (defun my-previous-line () (interactive) (previous-line) (recenter)) (global-set-key (kbd "<up>") 'my-previous-line)
(eval-after-load "eww" '(progn (define-key eww-mode-map (kbd "<mouse-1>") 'my-next-line) (define-key eww-mode-map (kbd "<mouse-2>") 'define-word-at-point) (define-key eww-mode-map (kbd "<mouse-4>") 'my-previous-line) (define-key eww-mode-map (kbd "<down-mouse-4>") 'nil) (define-key eww-mode-map (kbd "<mouse-5>") 'my-next-line) (define-key eww-mode-map (kbd "<down-mouse-5>") 'nil) (define-key eww-mode-map (kbd "<mouse-3>") 'my-previous-line) (define-key eww-mode-map (kbd "<mouse-8>") 'backward-word) (define-key eww-mode-map (kbd "<mouse-9>") 'forward-word)))
(defun kd/cancel-last-timer () (interactive) (cancel-timer (car (last timer-list))))
;; Emacs C source directory (let ((src-dir "~/ProjectOrg/emacs/emacs/src")) (if (file-directory-p src-dir) (setq source-directory src-dir)))
前提: ~/ProjectOrg/emacs
にEmacsのソースコードを配置しておく。
delve-mode
delve-mode は M-x gdb
と同じインターフェースで扱えるパッケージ。benma/go-dlv.elで配布されているものを持ってきた。
;;; go-dlv.el --- Go Delve - Debug Go programs interactively with the GUD. ;; Copyright (C) 2015, 2019 Marko Bencun ;; Author: Marko Bencun <mbencun@gmail.com> ;; URL: https://github.com/benma/go-dlv.el/ ;; Version: 0.6 ;; Package-Requires: ((go-mode "1.3.1")) ;; Keywords: Go, debug, debugger, delve, interactive, gud ;; This file is part of go-dlv. ;; go-dlv is free software: you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation, either version 3 of the License, or ;; (at your option) any later version. ;; go-dlv is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License ;; along with go-dlv. If not, see <http://www.gnu.org/licenses/>. ;;; Installation ;; If you are using Emacs 24 or later, you can get go-dlv from [melpa](https://melpa.org/) with the package manager. ;; Add the following code to your init file. ;; ---------------------------------------------------------- ;; (add-to-list 'load-path "folder-in-which-go-dlv-files-are-in/") ;; if the files are not already in the load path ;; (require 'go-dlv) ;; ---------------------------------------------------------- ;;; Code: ;; The code below is based on gud's pdb debugger, adapted to dlv: ;; https://github.com/emacs-mirror/emacs/blob/8badbad184c75d6a9b17b72900ca091a1bd11397/lisp/progmodes/gud.el#L1594-1698 (require 'gud) (require 'go-mode) ;; Sample marker lines: ;; > main.main() ./test.go:10 (hits goroutine(5):1 total:1) ;; > [unrecovered-panic] runtime.fatalpanic() /usr/lib/golang/src/runtime/panic.go:681 (hits goroutine(16):1 total:1) (PC: 0x435140) ;; Frame 2: /usr/lib/golang/src/testing/testing.go:792 (PC: 50fc82) (defvar go-dlv-marker-regexp "^\\(?:\\(?:> .+?(.*?) \\)\\|\\(?:Frame [0-9]+: \\)\\)\\(.+?\\)\\:\\([0-9]+\\)") (defvar go-dlv-marker-regexp-file-group 1) (defvar go-dlv-marker-regexp-line-group 2) (defvar go-dlv-marker-regexp-start "^> ") (defvar go-dlv-marker-acc "") (make-variable-buffer-local 'go-dlv-marker-acc) ;; There's no guarantee that Emacs will hand the filter the entire ;; marker at once; it could be broken up across several strings. We ;; might even receive a big chunk with several markers in it. If we ;; receive a chunk of text which looks like it might contain the ;; beginning of a marker, we save it here between calls to the ;; filter. (defun go-dlv-marker-filter (string) (setq go-dlv-marker-acc (concat go-dlv-marker-acc string)) (let ((output "")) ;; Process all the complete markers in this chunk. (while (string-match go-dlv-marker-regexp go-dlv-marker-acc) (setq ;; Extract the frame position from the marker. gud-last-frame (let ((file (match-string go-dlv-marker-regexp-file-group go-dlv-marker-acc)) (line (string-to-number (match-string go-dlv-marker-regexp-line-group go-dlv-marker-acc)))) (cons file line)) ;; Output everything instead of the below output (concat output (substring go-dlv-marker-acc 0 (match-end 0))) ;; ;; Append any text before the marker to the output we're going ;; ;; to return - we don't include the marker in this text. ;; output (concat output ;; (substring go-dlv-marker-acc 0 (match-beginning 0))) ;; Set the accumulator to the remaining text. go-dlv-marker-acc (substring go-dlv-marker-acc (match-end 0)))) ;; Does the remaining text look like it might end with the ;; beginning of another marker? If it does, then keep it in ;; go-dlv-marker-acc until we receive the rest of it. Since we ;; know the full marker regexp above failed, it's pretty simple to ;; test for marker starts. (if (string-match go-dlv-marker-regexp-start go-dlv-marker-acc) (progn ;; Everything before the potential marker start can be output. (setq output (concat output (substring go-dlv-marker-acc 0 (match-beginning 0)))) ;; Everything after, we save, to combine with later input. (setq go-dlv-marker-acc (substring go-dlv-marker-acc (match-beginning 0)))) (setq output (concat output go-dlv-marker-acc) go-dlv-marker-acc "")) output)) (define-obsolete-variable-alias 'go-dlv-command-name 'gud-dlv-command-name "0.4") (defcustom gud-dlv-command-name "dlv" "File name for executing the Go Delve debugger. This should be an executable on your path, or an absolute file name." :type 'string :group 'gud) ;;;###autoload (defun dlv (command-line) "Run dlv on program FILE in buffer `*gud-FILE*'. The directory containing FILE becomes the initial working directory and source-file directory for your debugger." (interactive (list (gud-query-cmdline 'dlv "debug"))) (gud-common-init command-line nil 'go-dlv-marker-filter) (set (make-local-variable 'gud-minor-mode) 'dlv) (gud-def gud-break "break %d%f:%l" "\C-b" "Set breakpoint at current line.") (gud-def gud-trace "trace %d%f:%l" "\C-t" "Set trace at current line.") (gud-def gud-remove "clearall %d%f:%l" "\C-d" "Remove breakpoint at current line") (gud-def gud-step "step" "\C-s" "Step one source line with display.") (gud-def gud-finish "stepout" "\C-f" "Finish executing current function.") (gud-def gud-next "next" "\C-n" "Step one line (skip functions).") (gud-def gud-cont "continue" "\C-r" "Continue running program.") (gud-def gud-until "continue %d%f:%l" "\C-u" "Continue to current line.") (gud-def gud-print "print %e" "\C-p" "Evaluate Go expression at point.") (gud-def gud-watch "display -a %e" "\C-w" "Print expression at point on every step.") (gud-def gud-up "up %p" "<" "Up N stack frames (numeric arg).") (gud-def gud-down "down %p" ">" "Down N stack frames (numeric arg).") (setq comint-prompt-regexp "^(Dlv) *") (setq paragraph-start comint-prompt-regexp) (run-hooks 'go-dlv-mode-hook)) ;;;###autoload (defun dlv-current-func () "Debug the current program or test stopping at the beginning of the current function." (interactive) (let (current-test-name current-bench-name current-func-loc) ;; find the location of the current function and (if it is a test function) its name (save-excursion (when (go-beginning-of-defun) (setq current-func-loc (format "%s:%d" buffer-file-name (line-number-at-pos))) ;; Check for Test or Benchmark function, set current-test-name/current-bench-name (when (looking-at go-func-regexp) (let ((func-name (match-string 1))) (when (string-match-p "_test\.go$" buffer-file-name) (cond ((string-match-p "^Test\\|^Example" func-name) (setq current-test-name func-name)) ((string-match-p "^Benchmark" func-name) (setq current-bench-name func-name)))))))) (if current-func-loc (let (gud-buffer-name dlv-command) (cond (current-test-name (setq gud-buffer-name "*gud-test*") (setq dlv-command (concat gud-dlv-command-name " test -- -test.run " current-test-name))) (current-bench-name (setq gud-buffer-name "*gud-test*") (setq dlv-command (concat gud-dlv-command-name " test -- -test.run='^$' -test.bench=" current-bench-name))) (t (setq gud-buffer-name "*gud-debug*") (setq dlv-command (concat gud-dlv-command-name " debug")))) ;; stop the current active dlv session if any (let ((gud-buffer (get-buffer gud-buffer-name))) (when gud-buffer (kill-buffer gud-buffer))) ;; run dlv and stop at the beginning of the current function (dlv dlv-command) (gud-call (format "break %s" current-func-loc)) (gud-call "continue")) (error "Not in function")))) (provide 'go-dlv) ;;; go-dlv.el ends here