diff --git a/home/takeru/features/emacs/early-init.el b/home/takeru/features/emacs/early-init.el index b6dd238e..9c11fb41 100644 --- a/home/takeru/features/emacs/early-init.el +++ b/home/takeru/features/emacs/early-init.el @@ -5,7 +5,9 @@ (set-variable 'ns-use-native-fullscreen nil) (set-variable 'x-super-keysym 'meta) +(set-variable 'gc-cons-threshold (* 128 1024 1024)) (set-variable 'load-prefer-newer t) +(set-variable 'custom-file (locate-user-emacs-file ".custom.el")) ;; Keep native-comp warnings quiet during startup and async compilation. (set-variable 'native-comp-async-report-warnings-errors 'silent) diff --git a/home/takeru/features/emacs/init.el b/home/takeru/features/emacs/init.el index 2ab321fd..c3d236b5 100644 --- a/home/takeru/features/emacs/init.el +++ b/home/takeru/features/emacs/init.el @@ -20,6 +20,9 @@ ;;; Navigation / Completion (leaf *completion + :custom ((enable-recursive-minibuffers . t) + (read-buffer-completion-ignore-case . t) + (read-file-name-completion-ignore-case . t)) :url https://blog.tomoya.dev/posts/a-new-wave-has-arrived-at-emacs :url https://emacs-jp.slack.com/archives/C1B5WTJLQ/p1623851956426000 :url https://github.com/uwabami/emacs @@ -104,6 +107,26 @@ :custom ((eglot-autoshutdown . t) (eglot-extend-to-xref . t))) +(leaf company + :bind (("C-M-i" . company-complete) + (:company-active-map + ("C-n" . company-select-next) + ("C-p" . company-select-previous) + ("C-s" . company-filter-candidates) + ("C-i" . company-complete-selection))) + :custom-face ((company-preview-common . '((nil (:foreground "lightgrey" :underline t)))) + (company-scrollbar-bg . '((nil (:background "gray40")))) + (company-scrollbar-fg . '((nil (:background "orange")))) + (company-tooltip . '((nil (:foreground "black" :background "lightgrey")))) + (company-tooltip-common . '((nil (:foreground "black" :background "lightgrey")))) + (company-tooltip-common-selection . '((nil (:foreground "white" :background "steelblue")))) + (company-tooltip-selection . '((nil (:foreground "black" :background "steelblue"))))) + :blackout company-mode + :hook (after-init-hook . global-company-mode)) + +(leaf company-quickhelp + :global-minor-mode company-quickhelp-mode) + ;;; Version control (leaf browse-at-remote @@ -125,6 +148,19 @@ (leaf vc :custom (vc-follow-symlinks . t)) +(leaf magit + :bind (("C-x v s" . magit-status) + ("C-x v f" . magit-diff-buffer-file)) + :custom (magit-diff-refine-hunk . 'all) + :hook (git-commit-setup-hook . elim:git-commit-setup-hook-func) + :init (add-to-list 'process-coding-system-alist '("git" utf-8 . utf-8)) + :config + (defun elim:git-commit-setup-hook-func () + (flyspell-mode +1) + (set (make-local-variable + 'elim:auto-delete-trailing-whitespace-enable-p) nil)) + :blackout auto-revert-mode) + ;;; Programming languages ;; Lua development environment @@ -249,6 +285,9 @@ (leaf hl-line :global-minor-mode global-hl-line-mode) +(leaf font-core + :config (global-font-lock-mode t)) + (leaf menu-bar :if (eq system-type 'darwin) :global-minor-mode t) @@ -287,15 +326,109 @@ ;;; Input method +(leaf *skk + :config + (let* + ((home (getenv "HOME")) + (xdg-config-home (getenv "XDG_CONFIG_HOME")) + (skk-nix-directory (expand-file-name ".nix-profile/share/skk/" home)) + (skk-user-directory (expand-file-name "ddskk" xdg-config-home)) + + ;; List of dictionary files to use + (skk-dictionary-files + '("SKK-JISYO.L.utf8" + "SKK-JISYO.itaiji.utf8" + "SKK-JISYO.jinmei.utf8" + "SKK-JISYO.fullname.utf8" + "SKK-JISYO.propernoun.utf8" + "SKK-JISYO.geo.utf8" + "SKK-JISYO.station.utf8" + "SKK-JISYO.okinawa.utf8" + "SKK-JISYO.china_taiwan.utf8" + "SKK-JISYO.office.zipcode.utf8" + "SKK-JISYO.zipcode.utf8")) + + ;; Generate dictionary file list + (skk-extra-jisyo-file-list + (mapcar (lambda (filename) + (cons (expand-file-name filename skk-nix-directory) 'utf-8)) + skk-dictionary-files))) + + ;; Main SKK configuration + (leaf skk + :defun skk-save-jisyo + :bind* (("C-x C-j" . skk-mode) + ("C-x t" . nil) + ("C-x j" . nil)) + + :custom + ;; Basic settings + ((default-input-method . "japanese-skk") + (skk-user-directory . skk-user-directory) + (skk-jisyo-code . 'utf-8) + + ;; Display and UI settings + (skk-japanese-message-and-error . t) + (skk-kutouten-type . 'jp) + (skk-show-annotation . t) + + ;; Conversion and learning settings + (skk-count-private-jisyo-candidates-exactly . t) + (skk-share-private-jisyo . t) + (skk-henkan-strict-okuri-precedence . t) + (skk-check-okurigana-on-touroku . 'auto) + (skk-search-sagyo-henkaku . t) + + ;; Search settings + (skk-isearch-start-mode . 'latin) + + ;; Dictionary file settings (from Nix) + (skk-extra-jisyo-file-list . skk-extra-jisyo-file-list)) + + :config + ;; Auto-save dictionary settings (6-second interval) + (let ((auto-save-interval 6)) + (run-with-idle-timer auto-save-interval t + #'(lambda () (skk-save-jisyo +1)))))) + + ;; SKK posframe configuration (popup display for conversion candidates) + (leaf ddskk-posframe + :doc "Show Henkan tooltip for ddskk via posframe" + :after skk + :custom ((ddskk-posframe-mode . t)) + :blackout ddskk-posframe-mode)) + ;;; Editor enhancements (leaf *editing-basics + :preface + (defvar elim:auto-delete-trailing-whitespace-enable-p t) + (defun elim:editorconfig-mode-enabled-p () + (assoc 'editorconfig-mode minor-mode-alist)) + (defun elim:auto-delete-trailing-whitespace () + (and elim:auto-delete-trailing-whitespace-enable-p + (not (elim:editorconfig-mode-enabled-p)) + (delete-trailing-whitespace))) + :bind (("" . delete-char) + ("C-h" . delete-char) + ("C-m" . newline-and-indent)) :custom ((delete-by-moving-to-trash . t) - (kill-ring-max . 8192)) + (kill-ring-max . 8192) + (require-final-newline . t)) :config (keyboard-translate ?\C-h ?\C-?) + (line-number-mode) (put 'list-timers 'disabled nil) - (put 'scroll-left 'disabled nil)) + (put 'scroll-left 'disabled nil) + (set-default 'indent-tabs-mode nil) + (transient-mark-mode) + (leaf executable + :config + (defun elim:executable-make-buffer-file-executable-if-script-p () + (unless (string-match tramp-file-name-regexp (buffer-file-name)) + (executable-make-buffer-file-executable-if-script-p))) + :hook (after-save-hook . elim:executable-make-buffer-file-executable-if-script-p)) + :hook (before-save-hook . elim:auto-delete-trailing-whitespace)) ;;; System integration @@ -314,6 +447,39 @@ (atomic-chrome-edit-done-hook . elim:save-buffer-to-kill-ring))) +(leaf browse-url + :bind ("C-x m" . browse-url-at-point)) + +(leaf dictionary + :if (eq system-type 'darwin) + :defun elim:dictionary-search + :preface + (defun elim:dictionary-search (word) + (browse-url + (concat "dict:///" (url-hexify-string word)))) + (defun elim:dictionary-word () + (interactive) + (elim:dictionary-search + (substring-no-properties (thing-at-point 'word)))) + (defun elim:dictionary-region (beg end) + (interactive "r") + (elim:dictionary-search + (buffer-substring-no-properties beg end))) + :bind (("C-x e" . elim:dictionary-word) + ("C-x y" . elim:dictionary-region))) + +(leaf clipmon + :hook (after-init-hook . clipmon-mode-start) + :config + (when (fboundp 'gui-get-selection) + (defun clipmon--get-selection () + "Get the clipboard contents. With a hack for Mozilla products, to set + UTF8_STRING explicitly." + (ignore-errors (gui-get-selection 'CLIPBOARD 'UTF8_STRING))))) + +(leaf auth-source + :custom `(auth-sources . '(,(locate-user-emacs-file ".authinfo.plist")))) + (leaf direnv :global-minor-mode t) (leaf server @@ -336,26 +502,53 @@ 'kill-buffer-query-functions 'server-kill-buffer-query-function)) -;;; Persistence and utilities +(leaf google-translate + :defun google-translate-translate + :bind (("C-c t" . google-translate-enja-or-jaen)) + :custom (google-translate-backend-method . 'curl) + :url http://emacs.rubikitch.com/google-translate/ + :config + (defvar google-translate-english-chars "[:ascii:]" + "If the target string consists of that pattern, it is assumed to be English.") + (defun google-translate-enja-or-jaen (&optional initial-text) + "Translate the region, sentence, or a given text between English and Japanese. -(leaf *utilities +Replaces newlines with spaces to treat the text as a single sentence. +When called with a prefix argument (C-u), prompt for input in the minibuffer." + (interactive + ;; Define the interactive behavior in a list form for clarity. + (list (cond ((use-region-p) + ;; If a region is active, use its content as the argument. + (buffer-substring-no-properties (region-beginning) (region-end))) + (current-prefix-arg + ;; If a prefix arg is supplied (C-u), prompt for the string to translate. + (read-string "Google Translate (en/ja): "))))) + + ;; Use let* to bind variables sequentially, making the data flow clear. + (let* ( + ;; 1. Determine the target text to translate. + (target-text + (or initial-text ; Use the text from the interactive call if available. + ;; Otherwise, get the sentence at the current point. + (save-excursion + (thing-at-point 'sentence)))) + + ;; 2. Pre-process the text (replace newlines with spaces). + (processed-text (replace-regexp-in-string "\n" " " target-text)) + + ;; 3. Detect the source language. + (english-p (string-match-p "\\`[[:ascii:]]+\\'" processed-text)) + (source-lang (if english-p "en" "ja")) + (target-lang (if english-p "ja" "en"))) + + ;; 4. Execute the translation. + (deactivate-mark) ; Deactivate the mark before displaying the translation. + (google-translate-translate source-lang target-lang processed-text)))) + +;;; Persistence and editor tools + +(leaf *persistence :config - (leaf auth-source - :custom `(auth-sources . '(,(locate-user-emacs-file ".authinfo.plist")))) - (leaf browse-url - :bind ("C-x m" . browse-url-at-point)) - (leaf bs - :bind ("C-x C-b" . bs-show)) - (leaf clipmon - :hook (after-init-hook . clipmon-mode-start) - :config - (when (fboundp 'gui-get-selection) - (defun clipmon--get-selection () - "Get the clipboard contents. With a hack for Mozilla products, to set - UTF8_STRING explicitly." - (ignore-errors (gui-get-selection 'CLIPBOARD 'UTF8_STRING))))) - (leaf dabbrev - :custom ((dabbrev-abbrev-skip-leading-regexp . "\\$"))) (leaf desktop :defvar desktop-globals-to-save :custom `((desktop-base-file-name . ,(locate-user-emacs-file ".desktop.el")) @@ -369,38 +562,6 @@ (add-to-list 'desktop-globals-to-save 'kill-ring) (add-to-list 'desktop-globals-to-save 'log-edit-comment-ring) (add-to-list 'desktop-globals-to-save 'read-expression-history)) - (leaf find-func - :config - ;; C-x F => Find Function - ;; C-x V => Find Variable - ;; C-x K => Find Function on Key - (find-function-setup-keys)) - (leaf dictionary - :if (eq system-type 'darwin) - :defun elim:dictionary-search - :preface - (defun elim:dictionary-search (word) - (browse-url - (concat "dict:///" (url-hexify-string word)))) - (defun elim:dictionary-word () - (interactive) - (elim:dictionary-search - (substring-no-properties (thing-at-point 'word)))) - (defun elim:dictionary-region (beg end) - (interactive "r") - (elim:dictionary-search - (buffer-substring-no-properties beg end))) - :bind (("C-x e" . elim:dictionary-word) - ("C-x y" . elim:dictionary-region))) - (leaf help-fns - :bind (("H-b" . describe-binding) - ("H-f" . describe-function) - ("H-k" . describe-key) - ("H-v" . describe-variable))) - (leaf open-junk-file - :bind (("C-x C-z" . open-junk-file)) - :custom ((open-junk-file-format . "~/.junk/%Y/%m/%d-%H%M%S.") - (open-junk-file-find-file-function . 'find-file))) (leaf recentf :defvar recentf-auto-save-timer :custom `((recentf-auto-save-timer @@ -408,6 +569,22 @@ (recentf-max-saved-items . 512) (recentf-save-file . ,(locate-user-emacs-file ".recentf.el"))) :global-minor-mode t) + (leaf persistent-scratch + :defun persistent-scratch-setup-default + :custom `(persistent-scratch-save-file . ,(locate-user-emacs-file ".scratch.el")) + :config + (with-current-buffer "*scratch*" + (emacs-lock-mode 'kill)) + (persistent-scratch-setup-default))) + +(leaf *editor-tools + :config + (leaf dabbrev + :custom ((dabbrev-abbrev-skip-leading-regexp . "\\$"))) + (leaf open-junk-file + :bind (("C-x C-z" . open-junk-file)) + :custom ((open-junk-file-format . "~/.junk/%Y/%m/%d-%H%M%S.") + (open-junk-file-find-file-function . 'find-file))) (leaf sort :defun elim:sort-lines-nocase :config @@ -417,88 +594,78 @@ (defvar sort-fold-case) (let ((sort-fold-case t)) (call-interactively 'sort-lines))) - (defalias 'sort-lines-nocase #'elim:sort-lines-nocase))) - -(leaf *environments - :custom `((enable-recursive-minibuffers . t) - (gc-cons-threshold . ,(* 128 1024 1024)) - (use-dialog-box . nil) - (user-mail-address . "takeru.naito@gmail.com") - (user-full-name . "Takeru Naito")) - :config - (defalias 'yes-or-no-p 'y-or-n-p) - (leaf cus-edit - :doc "Just prevent appending to this file (not load at startup)." - :custom `((custom-file . ,(locate-user-emacs-file ".custom.el")))) - (leaf simple - :defun elim:editorconfig-mode-enabled-p - :preface - (defvar elim:auto-delete-trailing-whitespace-enable-p t) - (defun elim:editorconfig-mode-enabled-p () - (assoc 'editorconfig-mode minor-mode-alist)) - (defun elim:auto-delete-trailing-whitespace () - (and elim:auto-delete-trailing-whitespace-enable-p - (not (elim:editorconfig-mode-enabled-p)) - (delete-trailing-whitespace))) - :bind (("" . delete-char) - ("C-h" . delete-char) - ("C-m" . newline-and-indent) - ("C-x |" . split-window-right) - ("C-x -" . split-window-below)) - :config - :global-minor-mode line-number-mode transient-mark-mode - :hook (before-save-hook . elim:auto-delete-trailing-whitespace))) + (defalias 'sort-lines-nocase #'elim:sort-lines-nocase)) + (leaf wgrep + :custom ((wgrep-auto-save-buffer . t)))) + +;;; Identity + +(leaf *identity + :custom `((user-mail-address . "takeru.naito@gmail.com") + (user-full-name . "Takeru Naito"))) -(leaf *interfaces +;;; Display and interaction + +(leaf *display-and-interaction :custom ((frame-title-format . `(" %b " (buffer-file-name "( %f )"))) (inhibit-startup-screen . t) (mouse-drag-copy-region . t) - (read-buffer-completion-ignore-case . t) - (read-file-name-completion-ignore-case . t) - (require-final-newline . t) (ring-bell-function . 'ignore) (scroll-conservatively . 1) (select-active-regions . nil) (show-trailing-whitespace . nil) (truncate-lines . nil) + (use-dialog-box . nil) (visible-bell . t)) :config + (defalias 'yes-or-no-p 'y-or-n-p) (put 'dired-find-alternate-file 'disabled nil) (put 'narrow-to-region 'disabled nil) (put 'set-goal-column 'disabled nil) - (set-default 'indent-tabs-mode nil) (set-default 'cursor-in-non-selected-windows nil) - (leaf buffer-move - :bind (("M-g h" . buf-move-left) - ("M-g j" . buf-move-down) - ("M-g k" . buf-move-up) - ("M-g l" . buf-move-right))) - (leaf company - :bind (("C-M-i" . company-complete) - (:company-active-map - ("C-n" . company-select-next) - ("C-p" . company-select-previous) - ("C-s" . company-filter-candidates) - ("C-i" . company-complete-selection))) - :custom-face ((company-preview-common . '((nil (:foreground "lightgrey" :underline t)))) - (company-scrollbar-bg . '((nil (:background "gray40")))) - (company-scrollbar-fg . '((nil (:background "orange")))) - (company-tooltip . '((nil (:foreground "black" :background "lightgrey")))) - (company-tooltip-common . '((nil (:foreground "black" :background "lightgrey")))) - (company-tooltip-common-selection . '((nil (:foreground "white" :background "steelblue")))) - (company-tooltip-selection . '((nil (:foreground "black" :background "steelblue"))))) - :blackout company-mode - :hook (after-init-hook . global-company-mode)) - (leaf company-quickhelp - :global-minor-mode company-quickhelp-mode) - (leaf executable + (leaf bs + :bind ("C-x C-b" . bs-show)) + (leaf find-func :config - (defun elim:executable-make-buffer-file-executable-if-script-p () - (unless (string-match tramp-file-name-regexp (buffer-file-name)) - (executable-make-buffer-file-executable-if-script-p))) - :hook (after-save-hook . elim:executable-make-buffer-file-executable-if-script-p)) - (leaf font-core - :config (global-font-lock-mode t)) + ;; C-x F => Find Function + ;; C-x V => Find Variable + ;; C-x K => Find Function on Key + (find-function-setup-keys)) + (leaf help-fns + :bind (("H-b" . describe-binding) + ("H-f" . describe-function) + ("H-k" . describe-key) + ("H-v" . describe-variable))) + (leaf help + :config (temp-buffer-resize-mode t)) + (leaf *dired + :config + (leaf dired + :bind (:dired-mode-map + ("SPC" . elim:dired-toggle-mark) + ("r" . dired-toggle-read-only)) + :custom ((dired-recursive-copies . 'always) + (dired-recursive-deletes . 'always)) + :defun dired-mark dired-unmark + :preface + ;; Mark with space (like the FD) + (defun elim:dired-toggle-mark (arg) + "Toggle the current (or next ARG) files." + ;; Based on S.Namba Sat Aug 10 12:20:36 1996 + ;; Modernized for current Emacs + (interactive "P") + (let ((current-mark (char-after (line-beginning-position)))) + (if (eq current-mark ?\s) ; If unmarked (space) + (dired-mark arg) ; Mark it + (dired-unmark arg))))) ; If marked, unmark it + (leaf dired-x + :custom ((dired-bind-jump . nil) + (dired-guess-shell-alist-user + . '(("\\.tar\\.gz\\'" "tar tzvf") + ("\\.taz\\'" "tar ztvf") + ("\\.tar\\.bz2\\'" "tar tjvf") + ("\\.zip\\'" "unzip -l") + ("\\.\\(g\\|\\) z\\'" "zcat")))))) (leaf mouse :bind (("C-" . nil) ("C-" . nil) @@ -512,50 +679,60 @@ :config (push '("*Google Translate*") popwin:special-display-config) :global-minor-mode t) - (leaf rotate) (leaf select :custom ((select-enable-primary . nil) (select-enable-clipboard . t) (selection-coding-system . 'utf-8))) - (leaf tab-bar - :doc "frame-local tabs with named persistent window configurations" - :tag "builtin" - :added "2022-02-09" - :bind-keymap ("C-z" . tab-bar-map) - :bind `(("M-{" . tab-previous) - ("M-}" . tab-next) - (:tab-bar-map - ("k" . tab-close) - ("c" . tab-new) - ("C-k" . tab-close) - ("n" . tab-next) - ("p" . tab-previous) - ("C-SPC" . tab-recent) - ,@(mapcar (lambda (i) - (cons (number-to-string i) 'tab-select)) - (number-sequence 0 9)))) - :custom ((tab-bar-new-tab-choice . "*scratch*") - (tab-bar-tab-hints . t)) - :custom-face - ((tab-bar-tab . '((nil (:foreground "#112" :background "#ccc")))) - (tab-bar-tab-inactive . '((nil (:foreground "#ccc" :background "#112"))))) - :global-minor-mode t) (leaf uniquify :custom ((uniquify-buffer-name-style . 'post-forward-angle-brackets) (uniquify-ignore-buffers-re . "*[^*]+*") (uniquify-min-dir-content . 1))) - (leaf wgrep - :custom ((wgrep-auto-save-buffer . t))) (leaf which-key :hook (after-init-hook . which-key-mode)) - (leaf windmove - :custom ((windmove-wrap-around . t)) - :bind (("C-c C-b" . windmove-left) - ("C-c C-n" . windmove-down) - ("C-c C-p" . windmove-up) - ("C-c C-f" . windmove-right)))) - -(leaf *minor-modes + (leaf *window-navigation + :config + (leaf buffer-move + :bind (("M-g h" . buf-move-left) + ("M-g j" . buf-move-down) + ("M-g k" . buf-move-up) + ("M-g l" . buf-move-right))) + (leaf rotate) + (leaf *window-commands + :bind (("C-x |" . split-window-right) + ("C-x -" . split-window-below))) + (leaf tab-bar + :doc "frame-local tabs with named persistent window configurations" + :tag "builtin" + :added "2022-02-09" + :bind-keymap ("C-z" . tab-bar-map) + :bind `(("M-{" . tab-previous) + ("M-}" . tab-next) + (:tab-bar-map + ("k" . tab-close) + ("c" . tab-new) + ("C-k" . tab-close) + ("n" . tab-next) + ("p" . tab-previous) + ("C-SPC" . tab-recent) + ,@(mapcar (lambda (i) + (cons (number-to-string i) 'tab-select)) + (number-sequence 0 9)))) + :custom ((tab-bar-new-tab-choice . "*scratch*") + (tab-bar-tab-hints . t)) + :custom-face + ((tab-bar-tab . '((nil (:foreground "#112" :background "#ccc")))) + (tab-bar-tab-inactive . '((nil (:foreground "#ccc" :background "#112"))))) + :global-minor-mode t) + (leaf windmove + :custom ((windmove-wrap-around . t)) + :bind (("C-c C-b" . windmove-left) + ("C-c C-n" . windmove-down) + ("C-c C-p" . windmove-up) + ("C-c C-f" . windmove-right))))) + +;;; Editor modes + +(leaf *editor-modes :config (leaf anzu :bind (([remap query-replace] . anzu-query-replace) @@ -571,34 +748,6 @@ :leaf-defer nil :custom ((auto-save-visited-interval . 0.5)) :global-minor-mode t) - (leaf *dired - :config - (leaf dired - :bind (:dired-mode-map - ("SPC" . elim:dired-toggle-mark) - ("r" . dired-toggle-read-only)) - :custom ((dired-recursive-copies . 'always) - (dired-recursive-deletes . 'always)) - :defun dired-mark dired-unmark - :preface - ;; Mark with space (like the FD) - (defun elim:dired-toggle-mark (arg) - "Toggle the current (or next ARG) files." - ;; Based on S.Namba Sat Aug 10 12:20:36 1996 - ;; Modernized for current Emacs - (interactive "P") - (let ((current-mark (char-after (line-beginning-position)))) - (if (eq current-mark ?\s) ; If unmarked (space) - (dired-mark arg) ; Mark it - (dired-unmark arg))))) ; If marked, unmark it - (leaf dired-x - :custom ((dired-bind-jump . nil) - (dired-guess-shell-alist-user - . '(("\\.tar\\.gz\\'" "tar tzvf") - ("\\.taz\\'" "tar ztvf") - ("\\.tar\\.bz2\\'" "tar tjvf") - ("\\.zip\\'" "unzip -l") - ("\\.\\(g\\|\\) z\\'" "zcat")))))) (leaf diff-mode :custom-face ((diff-added . '((nil (:foreground "white" :background "dark green")))) @@ -624,62 +773,11 @@ (leaf flyspell :custom ((ispell-dictionary . "american") (flyspell-use-meta-tab . nil))) - (leaf google-translate - :defun google-translate-translate - :bind (("C-c t" . google-translate-enja-or-jaen)) - :custom (google-translate-backend-method . 'curl) - :url http://emacs.rubikitch.com/google-translate/ - :config - (defvar google-translate-english-chars "[:ascii:]" - "If the target string consists of that pattern, it is assumed to be English.") - (defun google-translate-enja-or-jaen (&optional initial-text) - "Translate the region, sentence, or a given text between English and Japanese. - -Replaces newlines with spaces to treat the text as a single sentence. -When called with a prefix argument (C-u), prompt for input in the minibuffer." - (interactive - ;; Define the interactive behavior in a list form for clarity. - (list (cond ((use-region-p) - ;; If a region is active, use its content as the argument. - (buffer-substring-no-properties (region-beginning) (region-end))) - (current-prefix-arg - ;; If a prefix arg is supplied (C-u), prompt for the string to translate. - (read-string "Google Translate (en/ja): "))))) - - ;; Use let* to bind variables sequentially, making the data flow clear. - (let* ( - ;; 1. Determine the target text to translate. - (target-text - (or initial-text ; Use the text from the interactive call if available. - ;; Otherwise, get the sentence at the current point. - (save-excursion - (thing-at-point 'sentence)))) - - ;; 2. Pre-process the text (replace newlines with spaces). - (processed-text (replace-regexp-in-string "\n" " " target-text)) - - ;; 3. Detect the source language. - (english-p (string-match-p "\\`[[:ascii:]]+\\'" processed-text)) - (source-lang (if english-p "en" "ja")) - (target-lang (if english-p "ja" "en"))) - - ;; 4. Execute the translation. - (deactivate-mark) ; Deactivate the mark before displaying the translation. - (google-translate-translate source-lang target-lang processed-text)))) - (leaf help - :config (temp-buffer-resize-mode t)) (leaf hideshow :bind ((:hs-minor-mode-map ("C-c C-M-c" . hs-toggle-hiding) ("C-c h" . hs-toggle-hiding) ("C-c l" . hs-hide-level)))) - (leaf persistent-scratch - :defun persistent-scratch-setup-default - :custom `(persistent-scratch-save-file . ,(locate-user-emacs-file ".scratch.el")) - :config - (with-current-buffer "*scratch*" - (emacs-lock-mode 'kill)) - (persistent-scratch-setup-default)) (leaf projectile :bind (("M-t" . projectile-command-map)) :global-minor-mode t @@ -693,77 +791,6 @@ When called with a prefix argument (C-u), prompt for input in the minibuffer." :tag "builtin" :added "2024-08-24" :custom ((global-so-long-mode . t))) - (leaf *skk - :config - (let* - ((home (getenv "HOME")) - (xdg-config-home (getenv "XDG_CONFIG_HOME")) - (skk-nix-directory (expand-file-name ".nix-profile/share/skk/" home)) - (skk-user-directory (expand-file-name "ddskk" xdg-config-home)) - - ;; List of dictionary files to use - (skk-dictionary-files - '("SKK-JISYO.L.utf8" - "SKK-JISYO.itaiji.utf8" - "SKK-JISYO.jinmei.utf8" - "SKK-JISYO.fullname.utf8" - "SKK-JISYO.propernoun.utf8" - "SKK-JISYO.geo.utf8" - "SKK-JISYO.station.utf8" - "SKK-JISYO.okinawa.utf8" - "SKK-JISYO.china_taiwan.utf8" - "SKK-JISYO.office.zipcode.utf8" - "SKK-JISYO.zipcode.utf8")) - - ;; Generate dictionary file list - (skk-extra-jisyo-file-list - (mapcar (lambda (filename) - (cons (expand-file-name filename skk-nix-directory) 'utf-8)) - skk-dictionary-files))) - - ;; Main SKK configuration - (leaf skk - :defun skk-save-jisyo - :bind* (("C-x C-j" . skk-mode) - ("C-x t" . nil) - ("C-x j" . nil)) - - :custom - ;; Basic settings - ((default-input-method . "japanese-skk") - (skk-user-directory . skk-user-directory) - (skk-jisyo-code . 'utf-8) - - ;; Display and UI settings - (skk-japanese-message-and-error . t) - (skk-kutouten-type . 'jp) - (skk-show-annotation . t) - - ;; Conversion and learning settings - (skk-count-private-jisyo-candidates-exactly . t) - (skk-share-private-jisyo . t) - (skk-henkan-strict-okuri-precedence . t) - (skk-check-okurigana-on-touroku . 'auto) - (skk-search-sagyo-henkaku . t) - - ;; Search settings - (skk-isearch-start-mode . 'latin) - - ;; Dictionary file settings (from Nix) - (skk-extra-jisyo-file-list . skk-extra-jisyo-file-list)) - - :config - ;; Auto-save dictionary settings (6-second interval) - (let ((auto-save-interval 6)) - (run-with-idle-timer auto-save-interval t - #'(lambda () (skk-save-jisyo +1)))))) - - ;; SKK posframe configuration (popup display for conversion candidates) - (leaf ddskk-posframe - :doc "Show Henkan tooltip for ddskk via posframe" - :after skk - :custom ((ddskk-posframe-mode . t)) - :blackout ddskk-posframe-mode)) (leaf topsy :doc "Simple sticky header" :req "emacs-26.3" @@ -777,7 +804,9 @@ When called with a prefix argument (C-u), prompt for input in the minibuffer." (leaf vundo :bind (("C-x u" . vundo)))) -(leaf *major-modes +;;; Languages and authoring + +(leaf *languages-and-authoring :config (leaf cc-mode :defun c-toggle-auto-hungry-state @@ -813,18 +842,6 @@ When called with a prefix argument (C-u), prompt for input in the minibuffer." (leaf js :custom ((js-indent-level . 2))) (leaf json-mode) - (leaf magit - :bind (("C-x v s" . magit-status) - ("C-x v f" . magit-diff-buffer-file)) - :custom (magit-diff-refine-hunk . 'all) - :hook (git-commit-setup-hook . elim:git-commit-setup-hook-func) - :init (add-to-list 'process-coding-system-alist '("git" utf-8 . utf-8)) - :config - (defun elim:git-commit-setup-hook-func () - (flyspell-mode +1) - (set (make-local-variable - 'elim:auto-delete-trailing-whitespace-enable-p) nil)) - :blackout auto-revert-mode) (leaf markdown-mode :mode (("\\.md\\'" "\\ISSUE_EDITMSG\\'") . gfm-mode) :bind (:markdown-mode-map