Core Initialization

Core Emacs settings using use-package. This configures built-in Emacs behavior without external packages.

;;; init.el --- Summary  -*- lexical-binding: t; -*-
;;; Commentary:
;;; Code:

;; Server/headless environment detection
;; Detects if running without GUI (SSH, daemon, terminal)
(defvar emacs-server-mode
  (or (not (display-graphic-p))
      (daemonp)
      (getenv "SSH_CONNECTION")
      (getenv "EMACS_SERVER_MODE"))
  "Non-nil when running in server/headless mode (SSH, daemon, no GUI).
Set environment variable EMACS_SERVER_MODE=1 to force server mode.")

(use-package emacs
  :ensure nil
  :bind
  (("M-o"         . other-window)
   ("C-x r e"     . recentf)
   ("C-x C-b"     . ibuffer)
   ("C-x k"       .
      (lambda ()
        "Kill current buffer."
        (interactive)
        (kill-buffer (buffer-name))))
   ("RET"         . newline-and-indent)
   ("S-<return>"  .
      (lambda ()
        "New line and indent."
        (interactive)
        (end-of-line)
        (newline-and-indent)))
   ("C-z"         . nil)
   ("C-x C-z"     . nil)
   ("C-x C-k RET" . nil)
   ("C-S-j"       .
      (lambda()
        "Custom join line."
        (interactive)
        (let ((beg (pos-eol))
                      (end (progn
                                 (next-line)
                                 (back-to-indentation)
                                 (point))))
              (delete-region beg end))))
   (:map lisp-interaction-mode-map
               ("C-c C-c" . eval-last-sexp))
   (:map emacs-lisp-mode-map
               ("C-c C-c" . eval-last-sexp)))

  :custom
  (cursor-type '(bar . 3))
  (ad-redefinition-action 'accept)
  (column-number-mode nil)
  (line-number-mode nil)
  (completion-ignore-case t)
  (completions-detailed t)
  (completions-format 'one-column)
  (delete-by-moving-to-trash t)
  (display-line-numbers-width 6)
  (display-line-numbers-widen t)
  (delete-selection-mode 1)
  (enable-recursive minibuffers t)
  (find-ls-option '("-exec ls -ldh {} +" . "-ldh"))     ; find-dired results with human readable sizes
  (frame-resize-pixelwise t)
  (global-auto-revert-non-file-buffers t)
  (auto-revert-verbose nil)
  (help-window-select t)
  (history-length 300)
  (inhibit-startup-message t)
  (initial-buffer-choice 'remember-notes)
  (initial-major-mode 'org-mode)
  (initial-scratch-message nil)
  ;; (ispell-dictionary "en_US")
  (kill-do-not-save-duplicates t)
  (create-lockfiles nil)                                ; No backup files
  (make-backup-files nil)                               ; No backup files
  (backup-inhibited t)                                  ; No backup files
  (scroll-margin 0)
  (scroll-step 1)
  (scroll-conservatively 101)
  (pixel-scroll-precision-mode t)
  (pixel-scroll-precision-use-momentum nil)
  (ring-bell-function 'ignore)
  (read-answer-short t)
  (recentf-max-saved-items 300)                 ; default is 20
  (recentf-max-menu-items 15)
  (recentf-auto-cleanup (if (daemonp) 300 'never))
  (recentf-exclude (list "^/\\(?:ssh\\|su\\|sudo\\)?:"))
  (remote-file-name-inhibit-delete-by-moving-to-trash t)
  (remote-file-name-inhibit-auto-save t)
  (resize-mini-windows 'grow-only)
  (ring-bell-function #'ignore)
  (savehist-save-minibuffer-history t)  ; t is default
  (savehist-additional-variables
   '(kill-ring                                                  ; clipboard
       register-alist                                           ; macros
       mark-ring global-mark-ring                       ; marks
       search-ring regexp-search-ring)) ; searches
  (save-place-file (expand-file-name "saveplace" user-emacs-directory))
  (save-place-limit 600)
  (set-mark-command-repeat-pop t) ; So we can use C-u C-SPC C-SPC C-SPC... instead of C-u C-SPC C-u C-SPC...
  (split-width-threshold 170)     ; So vertical splits are preferred
  (split-height-threshold nil)
  (shr-use-colors nil)
  (switch-to-buffer-obey-display-actions t)
  (tab-always-indent 'complete)
  (tab-width 4)
  (tab-bar-close-button-show nil)
  (tab-bar-new-button-show nil)
  (tab-bar-tab-hints t)
  (treesit-font-lock-level 4)
  (truncate-lines t)
  (undo-limit (* 13 160000))
  (undo-strong-limit (* 13 240000))
  (undo-outer-limit (* 13 24000000))
  (use-dialog-box nil)
  (use-file-dialog nil)
  (use-short-answers t)
  (visible-bell nil)
  (window-combination-resize t)
  (window-resize-pixelwise nil)
  (xref-search-program 'ripgrep)
  (grep-command "grep --color=always -nH --null -e ")
  (grep-find-ignored-directories
   '("SCCS" "RCS" "CVS" "MCVS" ".src" ".svn" ".git" ".hg" ".bzr" "_MTN" "_darcs" "{arch}" "node_modules" "build" "dist"))
  (locale-coding-system 'utf-8)
  (keyboard-coding-system 'utf-8)
  (savehist-coding-system 'utf-8)
  (file-name-coding-system 'utf-8)
  (buffer-file-coding-system 'utf-8)
  (system-time-locale "C")
  (ns-pop-up-frames nil)
  (server-raise-frame t)

  :init
  (add-to-list 'default-frame-alist '(alpha-background . 100))
  (set-window-margins (selected-window) 2 0)
  (select-frame-set-input-focus (selected-frame))
  (global-auto-revert-mode 1)
  (global-goto-address-mode 1) ;; C-c RET to go
  (indent-tabs-mode nil)
  ;; While indent-tabs-mode nil prevents Emacs from inserting tabs for indentation, C-q TAB will always insert a literal tab character regardless of this setting.
  (recentf-mode 1)
  (repeat-mode 1)
  (savehist-mode 1)
  (save-place-mode 1)
  (winner-mode)
  (xterm-mouse-mode 1)
  (file-name-shadow-mode 1) ; allows us to type a new path without having to delete the current one
  (set-language-environment "Korean")
  (prefer-coding-system 'utf-8)
  (global-unset-key (kbd "S-SPC"))
  ;; Quick switch between input methods
  (defun fu/switch-to-bopomofo ()
      "Switch to Bopomofo input method."
      (interactive)
      (set-input-method "chinese-zozy"))
  (defun fu/switch-to-korean ()
      "Switch to Korean input method."
      (interactive)
      (set-input-method "korean-hangul"))
  (defun fu/switch-to-english ()
      "Disable input method (English)."
      (interactive)
      (deactivate-input-method))
  ;; Bind to function keys
  (global-set-key (kbd "<f5>") 'fu/switch-to-korean)
  (global-set-key (kbd "<f6>") 'fu/switch-to-bopomofo)

  (put 'narrow-to-region 'disabled nil)
  (message (emacs-init-time))
  :config
  ;; Makes everything accept utf-8 as default, so buffers with tsx and so
  ;; won't ask for encoding (because undecided-unix) every single keystroke
  (modify-coding-system-alist 'file "" 'utf-8)
  (setq custom-file (locate-user-emacs-file "custom-vars.el"))
  (load custom-file 'noerror 'nomessage)
  ;; Set line-number-mode with relative numbering
  (setq display-line-numbers-type 'absolute)
  (add-hook 'prog-mode-hook #'display-line-numbers-mode)
  ;; Add option "d" to whenever using C-x s or C-x C-c, allowing a quick preview
  ;; of the diff of what you're asked to save.
  (add-to-list 'save-some-buffers-action-alist
                         (list "d"
                                       (lambda (buffer) (diff-buffer-with-file (buffer-file-name buffer)))
                                       "show diff between the buffer and its file"))
  ;; On Terminal: changes the vertical separator to a full vertical line
  ;;              and truncation symbol to a right arrow
  (set-display-table-slot standard-display-table 'vertical-border ?\u2502)
  (set-display-table-slot standard-display-table 'truncation ?\u2192)

  ;; Ibuffer filters
  (setq ibuffer-saved-filter-groups
              '(("default"
             ("org" (or
                                 (mode . org-mode)
                                 (name . "^\\*Org Src")
                                 (name . "^\\*Org Agenda\\*$")))
             ("tramp" (name . "^\\*tramp.*"))
             ("emacs" (or
                                       (name . "^\\*scratch\\*$")
                                       (name . "^\\*Messages\\*$")
                                       (name . "^\\*Warnings\\*$")
                                       (name . "^\\*Shell Command Output\\*$")
                                       (name . "^\\*Async-native-compile-log\\*$")
                                       (name . "^\\*straight-")))
             ("ediff" (or
                                       (name . "^\\*ediff.*")
                                       (name . "^\\*Ediff.*")))
             ("dired" (mode . dired-mode))
             ("terminal" (or
                                              (mode . term-mode)
                                              (mode . shell-mode)
                                              (mode . eshell-mode)))
             ("help" (or
                                      (name . "^\\*Help\\*$")
                                      (name . "^\\*info\\*$")
                                      (name . "^\\*helpful"))))))
  (add-hook 'ibuffer-mode-hook
                      (lambda ()
                        (ibuffer-switch-to-saved-filter-groups "default")))
  (setq ibuffer-show-empty-filter-groups nil) ; don't show empty groups
  ;; So eshell git commands open an instance of THIS config of Emacs
  ;; (setenv "GIT_EDITOR" (format "emacs --init-dir=%s " (shell-quote-argument user-emacs-directory)))
  ;; So rebase from eshell opens with a bit of syntax highlight
  ;; (add-to-list 'auto-mode-alist '("/git-rebase-todo\\'" . conf-mode))

  ;; Reset GC after startup for better runtime performance
  (add-hook 'emacs-startup-hook
                      (lambda ()
                        (setq gc-cons-threshold (* 16 1024 1024)  ; 16MB
                                      gc-cons-percentage 0.1)))

  ;; Runs 'private.el' after Emacs inits
  (add-hook 'after-init-hook
                      (lambda ()
                        (let ((private-file (expand-file-name "private.el" user-emacs-directory)))
                              (when (file-exists-p private-file)
                                (load private-file)))))

  (add-hook 'server-visit-hook
          (lambda () (when (display-graphic-p) (select-frame-set-input-focus (selected-frame)))))

  (use-package use-package
      :custom
      (package-archives '(("melpa"  . "https://melpa.org/packages/")
                                              ("org"    . "https://orgmode.org/elpa/")
                                              ("elpa"   . "https://elpa.gnu.org/packages/")
                                              ("nongnu" . "https://elpa.nongnu.org/nongnu/")))
      (use-package-always-ensure t)
      (use-package-enable-at-startup nil)
      (package-native-compile t)
      (warning-minimun-level 'error))

  (eval-and-compile
      (add-to-list 'load-path (expand-file-name "elisp/settings/" user-emacs-directory)))

  (cond ((eq system-type 'windows-nt)
               (require 'windows-conf))
              ((eq system-type 'darwin)
               (require 'macos-conf))
              ((eq system-type 'gnu/linux)
               (require 'linux-conf)))

  (require 'theme-conf)
  (require 'window-conf)
  (require 'completion-conf)
  (require 'dired-conf)
  (require 'doc-conf)
  (require 'shell-conf)
  (require 'prog-conf)
  (require 'misc-conf)
  (require 'evil-conf)

  (require 'douzone-comet-config (expand-file-name "elisp/douzone-comet-config.el" user-emacs-directory) t)
  (require 'douzone-comet-service (expand-file-name "elisp/douzone-comet-service.el" user-emacs-directory) t)
  (require 'douzone-comet-ui (expand-file-name "elisp/douzone-comet-ui.el" user-emacs-directory) t)
  (require 'package-setup-function (expand-file-name "elisp/package-setup-function.el" user-emacs-directory) t))

(provide 'init)
;;; init.el ends here