update emac
This commit is contained in:
212
.emacs.d/init.el
212
.emacs.d/init.el
@@ -23,13 +23,112 @@
|
|||||||
(require 's)
|
(require 's)
|
||||||
(require 'dash)
|
(require 'dash)
|
||||||
(require 'popup)
|
(require 'popup)
|
||||||
|
(require 'simpc-mode)
|
||||||
|
;; Automatically enabling simpc-mode on files with extensions like .h, .c, .cpp, .hpp
|
||||||
|
(add-to-list 'auto-mode-alist '("\\.[hc]\\(pp\\)?\\'" . simpc-mode))
|
||||||
;; ctags for xref, with dumb-jump as fallback
|
;; ctags for xref, with dumb-jump as fallback
|
||||||
(require 'dumb-jump)
|
(require 'dumb-jump)
|
||||||
(setq dumb-jump-force-searcher 'grep)
|
(setq dumb-jump-force-searcher 'grep)
|
||||||
|
(setq dumb-jump-selector 'ivy)
|
||||||
(setq xref-show-definitions-function #'xref-show-definitions-completing-read)
|
(setq xref-show-definitions-function #'xref-show-definitions-completing-read)
|
||||||
(setq tags-revert-without-query t)
|
(setq tags-revert-without-query t)
|
||||||
(add-hook 'xref-backend-functions #'dumb-jump-xref-activate 100)
|
(add-hook 'xref-backend-functions #'dumb-jump-xref-activate 100)
|
||||||
|
|
||||||
|
;; eglot LSP client
|
||||||
|
;; When eglot is active, xref commands (F12, M-f12) automatically use LSP
|
||||||
|
;; instead of CTAGS. Eglot registers itself as a higher-priority xref backend.
|
||||||
|
(require 'eglot)
|
||||||
|
(setq eglot-autoshutdown t) ; shutdown server when last buffer is closed
|
||||||
|
(setq eglot-confirm-server-initiated-edits nil) ; don't ask for confirmation on renames
|
||||||
|
|
||||||
|
;; disable LSP visual indicators but keep diagnostics available
|
||||||
|
(add-to-list 'eglot-ignored-server-capabilities :documentHighlightProvider)
|
||||||
|
|
||||||
|
;; auto-confirm "modified buffer" prompts when jumping from diagnostics
|
||||||
|
(defun my-auto-confirm-modified-buffer (orig-fun prompt)
|
||||||
|
"Auto-confirm prompts about modified buffers having wrong location."
|
||||||
|
(if (string-match-p "has been modified.*wrong location" prompt)
|
||||||
|
t
|
||||||
|
(funcall orig-fun prompt)))
|
||||||
|
(advice-add 'y-or-n-p :around #'my-auto-confirm-modified-buffer)
|
||||||
|
;; hide squiggly underlines
|
||||||
|
(set-face-attribute 'flymake-error nil :underline nil)
|
||||||
|
(set-face-attribute 'flymake-warning nil :underline nil)
|
||||||
|
(set-face-attribute 'flymake-note nil :underline nil)
|
||||||
|
;; hide fringe indicators
|
||||||
|
(setq flymake-fringe-indicator-position nil)
|
||||||
|
|
||||||
|
;; Go: auto-start eglot (requires gopls: go install golang.org/x/tools/gopls@latest)
|
||||||
|
(add-hook 'go-mode-hook 'eglot-ensure)
|
||||||
|
|
||||||
|
(global-set-key (kbd "<f2>") 'eglot-rename)
|
||||||
|
(global-set-key (kbd "C-S-m") 'my-flymake-show-project-errors-warnings)
|
||||||
|
(global-set-key (kbd "<S-f2>") 'eglot-reconnect)
|
||||||
|
(global-set-key (kbd "C-t") 'my-lsp-find-workspace-symbol)
|
||||||
|
|
||||||
|
(defun my-flymake-show-project-errors-warnings ()
|
||||||
|
"Show project diagnostics, filtering out notes (only errors and warnings)."
|
||||||
|
(interactive)
|
||||||
|
;; Kill existing diagnostics buffer to force refresh
|
||||||
|
(when-let ((buf (get-buffer "*Flymake diagnostics*")))
|
||||||
|
(kill-buffer buf))
|
||||||
|
;; Refresh flymake on all project buffers
|
||||||
|
(dolist (buf (buffer-list))
|
||||||
|
(with-current-buffer buf
|
||||||
|
(when (and (bound-and-true-p flymake-mode)
|
||||||
|
(buffer-file-name))
|
||||||
|
(flymake-start))))
|
||||||
|
(flymake-show-project-diagnostics)
|
||||||
|
(run-at-time 0.1 nil
|
||||||
|
(lambda ()
|
||||||
|
(when-let ((buf (get-buffer "*Flymake diagnostics*")))
|
||||||
|
(with-current-buffer buf
|
||||||
|
(let ((inhibit-read-only t))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(while (not (eobp))
|
||||||
|
(if (looking-at ".*\\bnote\\b.*$")
|
||||||
|
(delete-region (line-beginning-position) (1+ (line-end-position)))
|
||||||
|
(forward-line 1)))))))))
|
||||||
|
|
||||||
|
(defun my-lsp-find-workspace-symbol ()
|
||||||
|
"Interactively search for symbols in workspace using LSP."
|
||||||
|
(interactive)
|
||||||
|
(if (eglot-managed-p)
|
||||||
|
(let ((server (eglot-current-server))
|
||||||
|
(root (project-root (project-current))))
|
||||||
|
(ivy-read "Symbol: "
|
||||||
|
(lambda (input)
|
||||||
|
(when (and input (>= (length input) 1))
|
||||||
|
(condition-case nil
|
||||||
|
(let* ((resp (jsonrpc-request server :workspace/symbol
|
||||||
|
`(:query ,input)))
|
||||||
|
(items (append resp nil)))
|
||||||
|
(delq nil
|
||||||
|
(mapcar (lambda (item)
|
||||||
|
(condition-case nil
|
||||||
|
(let* ((name (plist-get item :name))
|
||||||
|
(loc (plist-get item :location))
|
||||||
|
(uri (plist-get loc :uri))
|
||||||
|
(range (plist-get loc :range))
|
||||||
|
(start (plist-get range :start))
|
||||||
|
(line (1+ (plist-get start :line)))
|
||||||
|
(file (eglot-uri-to-path uri))
|
||||||
|
(rel-path (file-relative-name file root)))
|
||||||
|
(propertize (format "%s %s:%d" name rel-path line)
|
||||||
|
'file file
|
||||||
|
'line line))
|
||||||
|
(error nil)))
|
||||||
|
items)))
|
||||||
|
(error nil))))
|
||||||
|
:dynamic-collection t
|
||||||
|
:require-match t
|
||||||
|
:action (lambda (candidate)
|
||||||
|
(when (and candidate (get-text-property 0 'file candidate))
|
||||||
|
(find-file (get-text-property 0 'file candidate))
|
||||||
|
(goto-char (point-min))
|
||||||
|
(forward-line (1- (get-text-property 0 'line candidate)))))))
|
||||||
|
(call-interactively 'xref-find-apropos)))
|
||||||
|
|
||||||
;; vundo for visual undo tree
|
;; vundo for visual undo tree
|
||||||
(require 'vundo)
|
(require 'vundo)
|
||||||
(ivy-mode 1)
|
(ivy-mode 1)
|
||||||
@@ -61,6 +160,11 @@
|
|||||||
(setq-local tab-width 4)
|
(setq-local tab-width 4)
|
||||||
(setq-local stupid-indent-level 4)))
|
(setq-local stupid-indent-level 4)))
|
||||||
|
|
||||||
|
(add-hook 'simpc-mode-hook (lambda ()
|
||||||
|
(setq-local indent-tabs-mode t)
|
||||||
|
(setq-local tab-width 4)
|
||||||
|
(setq-local stupid-indent-level 4)))
|
||||||
|
|
||||||
(add-hook 'python-mode-hook (lambda ()
|
(add-hook 'python-mode-hook (lambda ()
|
||||||
(setq-local indent-tabs-mode nil)
|
(setq-local indent-tabs-mode nil)
|
||||||
(setq-local tab-width 4)
|
(setq-local tab-width 4)
|
||||||
@@ -81,9 +185,10 @@
|
|||||||
|
|
||||||
;; bottom panel settings (compilation, xref, etc.)
|
;; bottom panel settings (compilation, xref, etc.)
|
||||||
(setq compilation-scroll-output -1)
|
(setq compilation-scroll-output -1)
|
||||||
|
(setq compilation-save-buffers-predicate 'ignore)
|
||||||
|
|
||||||
;; bottom panel buffer patterns
|
;; bottom panel buffer patterns
|
||||||
(defvar my-bottom-panel-buffers '("\\*compilation\\*" "\\*xref\\*")
|
(defvar my-bottom-panel-buffers '("\\*compilation\\*" "\\*xref\\*" "\\*Flymake diagnostics.*\\*")
|
||||||
"List of buffer name patterns for bottom panel.")
|
"List of buffer name patterns for bottom panel.")
|
||||||
|
|
||||||
(defun my-bottom-panel-buffer-p (buf)
|
(defun my-bottom-panel-buffer-p (buf)
|
||||||
@@ -118,6 +223,8 @@
|
|||||||
'("\\*compilation\\*" (my-display-in-bottom-panel) (window-height . 0.25)))
|
'("\\*compilation\\*" (my-display-in-bottom-panel) (window-height . 0.25)))
|
||||||
(add-to-list 'display-buffer-alist
|
(add-to-list 'display-buffer-alist
|
||||||
'("\\*xref\\*" (my-display-in-bottom-panel) (window-height . 0.25)))
|
'("\\*xref\\*" (my-display-in-bottom-panel) (window-height . 0.25)))
|
||||||
|
(add-to-list 'display-buffer-alist
|
||||||
|
'("\\*Flymake diagnostics.*\\*" (my-display-in-bottom-panel) (window-height . 0.25)))
|
||||||
|
|
||||||
|
|
||||||
(defun my-bottom-panel-toggle ()
|
(defun my-bottom-panel-toggle ()
|
||||||
@@ -256,8 +363,16 @@
|
|||||||
(global-set-key (kbd "C-p") 'project-find-file)
|
(global-set-key (kbd "C-p") 'project-find-file)
|
||||||
(global-set-key (kbd "C-s") 'save-buffer)
|
(global-set-key (kbd "C-s") 'save-buffer)
|
||||||
(global-set-key (kbd "<f3>") 'my-select-theme)
|
(global-set-key (kbd "<f3>") 'my-select-theme)
|
||||||
(global-set-key (kbd "<f12>") 'xref-find-definitions)
|
(global-set-key (kbd "C-<mouse-1>") 'my-xref-find-definitions-at-click)
|
||||||
(global-set-key (kbd "<C-S-f12>") 'xref-pop-marker-stack)
|
(global-set-key (kbd "C-S-<mouse-1>") 'my-xref-find-references-at-click)
|
||||||
|
(global-set-key (kbd "<f12>") 'my-xref-find-definitions-same-pane)
|
||||||
|
(global-set-key (kbd "C-<f12>") 'xref-find-references)
|
||||||
|
(global-set-key (kbd "C-{") 'xref-go-back)
|
||||||
|
(global-set-key (kbd "C-}") 'xref-go-forward)
|
||||||
|
(global-set-key (kbd "C-]") 'stupid-indent)
|
||||||
|
(global-set-key (kbd "C-[") 'stupid-outdent)
|
||||||
|
(global-set-key (kbd "<mouse-3>") 'xref-go-back)
|
||||||
|
(global-set-key (kbd "<mouse-4>") 'xref-go-forward)
|
||||||
(global-set-key (kbd "C-q") 'save-buffers-kill-terminal)
|
(global-set-key (kbd "C-q") 'save-buffers-kill-terminal)
|
||||||
(global-set-key (kbd "C-l") 'my-select-line)
|
(global-set-key (kbd "C-l") 'my-select-line)
|
||||||
(global-set-key (kbd "C-e") 'my-copy-path-with-line)
|
(global-set-key (kbd "C-e") 'my-copy-path-with-line)
|
||||||
@@ -265,7 +380,8 @@
|
|||||||
(define-key isearch-mode-map (kbd "<return>") 'isearch-repeat-forward)
|
(define-key isearch-mode-map (kbd "<return>") 'isearch-repeat-forward)
|
||||||
(define-key isearch-mode-map (kbd "S-<return>") 'isearch-repeat-backward)
|
(define-key isearch-mode-map (kbd "S-<return>") 'isearch-repeat-backward)
|
||||||
(define-key isearch-mode-map (kbd "<backspace>") 'isearch-del-char)
|
(define-key isearch-mode-map (kbd "<backspace>") 'isearch-del-char)
|
||||||
(define-key isearch-mode-map (kbd "<escape>") 'isearch-exit)
|
(define-key isearch-mode-map (kbd "C-v") 'isearch-yank-kill)
|
||||||
|
(define-key isearch-mode-map (kbd "<escape>") 'my-isearch-cancel-or-exit)
|
||||||
(define-key isearch-mode-map (kbd "C-g") 'my-isearch-cancel-or-exit)
|
(define-key isearch-mode-map (kbd "C-g") 'my-isearch-cancel-or-exit)
|
||||||
|
|
||||||
(defun my-isearch-cancel-or-exit ()
|
(defun my-isearch-cancel-or-exit ()
|
||||||
@@ -274,11 +390,69 @@
|
|||||||
(if (string= isearch-string "")
|
(if (string= isearch-string "")
|
||||||
(isearch-cancel)
|
(isearch-cancel)
|
||||||
(isearch-exit)))
|
(isearch-exit)))
|
||||||
|
|
||||||
|
(defun my-move-line-up ()
|
||||||
|
"Move current line or region up one line."
|
||||||
|
(interactive)
|
||||||
|
(if (use-region-p)
|
||||||
|
(my-move-region-up)
|
||||||
|
(let ((col (current-column)))
|
||||||
|
(transpose-lines 1)
|
||||||
|
(forward-line -2)
|
||||||
|
(move-to-column col))))
|
||||||
|
|
||||||
|
(defun my-move-line-down ()
|
||||||
|
"Move current line or region down one line."
|
||||||
|
(interactive)
|
||||||
|
(if (use-region-p)
|
||||||
|
(my-move-region-down)
|
||||||
|
(let ((col (current-column)))
|
||||||
|
(forward-line 1)
|
||||||
|
(transpose-lines 1)
|
||||||
|
(forward-line -1)
|
||||||
|
(move-to-column col))))
|
||||||
|
|
||||||
|
(defun my-move-region-up ()
|
||||||
|
"Move selected region up one line, keeping selection."
|
||||||
|
(let* ((rbeg (region-beginning))
|
||||||
|
(rend (region-end))
|
||||||
|
(beg (save-excursion (goto-char rbeg) (line-beginning-position)))
|
||||||
|
(end (save-excursion (goto-char rend) (if (bolp) (point) (1+ (line-end-position)))))
|
||||||
|
(offset-from-beg (- rbeg beg))
|
||||||
|
(region-len (- rend rbeg))
|
||||||
|
(text (delete-and-extract-region beg end)))
|
||||||
|
(forward-line -1)
|
||||||
|
(let ((new-beg (point)))
|
||||||
|
(insert text)
|
||||||
|
(set-mark (+ new-beg offset-from-beg))
|
||||||
|
(goto-char (+ new-beg offset-from-beg region-len))
|
||||||
|
(setq deactivate-mark nil))))
|
||||||
|
|
||||||
|
(defun my-move-region-down ()
|
||||||
|
"Move selected region down one line, keeping selection."
|
||||||
|
(let* ((rbeg (region-beginning))
|
||||||
|
(rend (region-end))
|
||||||
|
(beg (save-excursion (goto-char rbeg) (line-beginning-position)))
|
||||||
|
(end (save-excursion (goto-char rend) (if (bolp) (point) (1+ (line-end-position)))))
|
||||||
|
(offset-from-beg (- rbeg beg))
|
||||||
|
(region-len (- rend rbeg))
|
||||||
|
(lines (count-lines beg end))
|
||||||
|
(text (delete-and-extract-region beg end)))
|
||||||
|
(forward-line 1)
|
||||||
|
(let ((new-beg (point)))
|
||||||
|
(insert text)
|
||||||
|
(set-mark (+ new-beg offset-from-beg))
|
||||||
|
(goto-char (+ new-beg offset-from-beg region-len))
|
||||||
|
(setq deactivate-mark nil))))
|
||||||
|
|
||||||
|
(global-set-key (kbd "M-<up>") 'my-move-line-up)
|
||||||
|
(global-set-key (kbd "M-<down>") 'my-move-line-down)
|
||||||
(setq isearch-wrap-pause 'no)
|
(setq isearch-wrap-pause 'no)
|
||||||
|
|
||||||
;; multiple cursors (vscode-style)
|
;; multiple cursors (vscode-style)
|
||||||
(setq mc/always-run-for-all t)
|
(setq mc/always-run-for-all t)
|
||||||
(global-set-key (kbd "C-S-<mouse-1>") 'mc/add-cursor-on-click)
|
(global-set-key (kbd "M-<down-mouse-1>") 'ignore)
|
||||||
|
(global-set-key (kbd "M-<mouse-1>") 'mc/add-cursor-on-click)
|
||||||
(global-set-key (kbd "C-M-<up>") (lambda () (interactive) (mc/mark-previous-lines 1)))
|
(global-set-key (kbd "C-M-<up>") (lambda () (interactive) (mc/mark-previous-lines 1)))
|
||||||
(global-set-key (kbd "C-M-<down>") (lambda () (interactive) (mc/mark-next-lines 1)))
|
(global-set-key (kbd "C-M-<down>") (lambda () (interactive) (mc/mark-next-lines 1)))
|
||||||
(define-key mc/keymap (kbd "<escape>") 'mc/keyboard-quit)
|
(define-key mc/keymap (kbd "<escape>") 'mc/keyboard-quit)
|
||||||
@@ -312,6 +486,32 @@
|
|||||||
(split-window-right)
|
(split-window-right)
|
||||||
(other-window 1)))))
|
(other-window 1)))))
|
||||||
|
|
||||||
|
(defun my-xref-find-definitions-same-pane ()
|
||||||
|
"Find definition and show it in the same pane.
|
||||||
|
Falls back to dumb-jump if xref fails."
|
||||||
|
(interactive)
|
||||||
|
(let ((identifier (thing-at-point 'symbol t)))
|
||||||
|
(if (null identifier)
|
||||||
|
(message "No symbol at point")
|
||||||
|
(condition-case nil
|
||||||
|
(let ((xrefs (xref-backend-definitions (xref-find-backend) identifier)))
|
||||||
|
(if xrefs
|
||||||
|
(xref-find-definitions identifier)
|
||||||
|
(dumb-jump-go)))
|
||||||
|
(error (dumb-jump-go))))))
|
||||||
|
|
||||||
|
(defun my-xref-find-definitions-at-click (event)
|
||||||
|
"Find definition of the symbol clicked on."
|
||||||
|
(interactive "e")
|
||||||
|
(mouse-set-point event)
|
||||||
|
(my-xref-find-definitions-same-pane))
|
||||||
|
|
||||||
|
(defun my-xref-find-references-at-click (event)
|
||||||
|
"Find references of the symbol clicked on."
|
||||||
|
(interactive "e")
|
||||||
|
(mouse-set-point event)
|
||||||
|
(xref-find-references (thing-at-point 'symbol t)))
|
||||||
|
|
||||||
;; custom bind minor mode
|
;; custom bind minor mode
|
||||||
;; this allows binding keys that override all other modes
|
;; this allows binding keys that override all other modes
|
||||||
(defvar my-keys-minor-mode-map
|
(defvar my-keys-minor-mode-map
|
||||||
@@ -471,8 +671,6 @@
|
|||||||
(visit-tags-table tags-path)
|
(visit-tags-table tags-path)
|
||||||
(message "TAGS generated and saved: %s" tags-path)))
|
(message "TAGS generated and saved: %s" tags-path)))
|
||||||
|
|
||||||
(global-set-key (kbd "M-<f12>") 'xref-find-references)
|
|
||||||
|
|
||||||
;; find and replace with modes
|
;; find and replace with modes
|
||||||
(defun my-find-replace ()
|
(defun my-find-replace ()
|
||||||
"Find and replace with mode selection: project, file, or selection."
|
"Find and replace with mode selection: project, file, or selection."
|
||||||
|
|||||||
127
.emacs.d/lisp/simpc-mode.el
Normal file
127
.emacs.d/lisp/simpc-mode.el
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
(require 'subr-x)
|
||||||
|
|
||||||
|
(defvar simpc-mode-syntax-table
|
||||||
|
(let ((table (make-syntax-table)))
|
||||||
|
;; C/C++ style comments
|
||||||
|
(modify-syntax-entry ?/ ". 124b" table)
|
||||||
|
(modify-syntax-entry ?* ". 23" table)
|
||||||
|
(modify-syntax-entry ?\n "> b" table)
|
||||||
|
;; Preprocessor stuff?
|
||||||
|
(modify-syntax-entry ?# "." table)
|
||||||
|
;; Chars are the same as strings
|
||||||
|
(modify-syntax-entry ?' "\"" table)
|
||||||
|
;; Treat <> as punctuation (needed to highlight C++ keywords
|
||||||
|
;; properly in template syntax)
|
||||||
|
(modify-syntax-entry ?< "." table)
|
||||||
|
(modify-syntax-entry ?> "." table)
|
||||||
|
|
||||||
|
(modify-syntax-entry ?& "." table)
|
||||||
|
(modify-syntax-entry ?% "." table)
|
||||||
|
table))
|
||||||
|
|
||||||
|
(defun simpc-types ()
|
||||||
|
'("char" "int" "long" "short" "void" "bool" "float" "double" "signed" "unsigned"
|
||||||
|
"char16_t" "char32_t" "char8_t"
|
||||||
|
"int8_t" "uint8_t" "int16_t" "uint16_t" "int32_t" "uint32_t" "int64_t" "uint64_t"
|
||||||
|
"uintptr_t"
|
||||||
|
"size_t"
|
||||||
|
"va_list"))
|
||||||
|
|
||||||
|
(defun simpc-keywords ()
|
||||||
|
'("auto" "break" "case" "const" "continue" "default" "do"
|
||||||
|
"else" "enum" "extern" "for" "goto" "if" "register"
|
||||||
|
"return" "sizeof" "static" "struct" "switch" "typedef"
|
||||||
|
"union" "volatile" "while" "alignas" "alignof" "and"
|
||||||
|
"and_eq" "asm" "atomic_cancel" "atomic_commit" "atomic_noexcept" "bitand"
|
||||||
|
"bitor" "catch" "class" "co_await"
|
||||||
|
"co_return" "co_yield" "compl" "concept" "const_cast" "consteval" "constexpr"
|
||||||
|
"constinit" "decltype" "delete" "dynamic_cast" "explicit" "export" "false"
|
||||||
|
"friend" "inline" "mutable" "namespace" "new" "noexcept" "not" "not_eq"
|
||||||
|
"nullptr" "operator" "or" "or_eq" "private" "protected" "public" "reflexpr"
|
||||||
|
"reinterpret_cast" "requires" "static_assert" "static_cast" "synchronized"
|
||||||
|
"template" "this" "thread_local" "throw" "true" "try" "typeid" "typename"
|
||||||
|
"using" "virtual" "wchar_t" "xor" "xor_eq"))
|
||||||
|
|
||||||
|
(defun simpc-font-lock-keywords ()
|
||||||
|
(list
|
||||||
|
`("# *\\(warn\\|error\\)" . font-lock-warning-face)
|
||||||
|
`("# *[#a-zA-Z0-9_]+" . font-lock-preprocessor-face)
|
||||||
|
`("# *include\\(?:_next\\)?\\s-+\\(\\(<\\|\"\\).*\\(>\\|\"\\)\\)" . (1 font-lock-string-face))
|
||||||
|
`("\\(?:enum\\|struct\\)\\s-+\\([a-zA-Z0-9_]+\\)" . (1 font-lock-type-face))
|
||||||
|
`(,(regexp-opt (simpc-keywords) 'symbols) . font-lock-keyword-face)
|
||||||
|
`(,(regexp-opt (simpc-types) 'symbols) . font-lock-type-face)))
|
||||||
|
|
||||||
|
(defun simpc--previous-non-empty-line ()
|
||||||
|
"Returns either NIL when there is no such line or a pair (line . indentation)"
|
||||||
|
(save-excursion
|
||||||
|
;; If you are on the first line, but not at the beginning of buffer (BOB) the `(bobp)`
|
||||||
|
;; function does not return `t`. So we have to move to the beginning of the line first.
|
||||||
|
;; TODO: feel free to suggest a better approach for checking BOB here.
|
||||||
|
(move-beginning-of-line nil)
|
||||||
|
(if (bobp)
|
||||||
|
;; If you are standing at the BOB, you by definition don't have a previous non-empty line.
|
||||||
|
nil
|
||||||
|
;; Moving one line backwards because the current line is by definition is not
|
||||||
|
;; the previous non-empty line.
|
||||||
|
(forward-line -1)
|
||||||
|
;; Keep moving backwards until we hit BOB or a non-empty line.
|
||||||
|
(while (and (not (bobp))
|
||||||
|
(string-empty-p
|
||||||
|
(string-trim-right
|
||||||
|
(thing-at-point 'line t))))
|
||||||
|
(forward-line -1))
|
||||||
|
|
||||||
|
(if (string-empty-p
|
||||||
|
(string-trim-right
|
||||||
|
(thing-at-point 'line t)))
|
||||||
|
;; If after moving backwards for this long we still look at an empty
|
||||||
|
;; line we by definition didn't find the previous non-empty line.
|
||||||
|
nil
|
||||||
|
;; We found the previous non-empty line!
|
||||||
|
(cons (thing-at-point 'line t)
|
||||||
|
(current-indentation))))))
|
||||||
|
|
||||||
|
(defun simpc--desired-indentation ()
|
||||||
|
(let ((prev (simpc--previous-non-empty-line)))
|
||||||
|
(if (not prev)
|
||||||
|
(current-indentation)
|
||||||
|
(let ((indent-len 4)
|
||||||
|
(cur-line (string-trim-right (thing-at-point 'line t)))
|
||||||
|
(prev-line (string-trim-right (car prev)))
|
||||||
|
(prev-indent (cdr prev)))
|
||||||
|
(cond
|
||||||
|
((string-match-p "^\\s-*switch\\s-*(.+)" prev-line)
|
||||||
|
prev-indent)
|
||||||
|
((and (string-suffix-p "{" prev-line)
|
||||||
|
(string-prefix-p "}" (string-trim-left cur-line)))
|
||||||
|
prev-indent)
|
||||||
|
((string-suffix-p "{" prev-line)
|
||||||
|
(+ prev-indent indent-len))
|
||||||
|
((string-prefix-p "}" (string-trim-left cur-line))
|
||||||
|
(max (- prev-indent indent-len) 0))
|
||||||
|
((string-suffix-p ":" prev-line)
|
||||||
|
(if (string-suffix-p ":" cur-line)
|
||||||
|
prev-indent
|
||||||
|
(+ prev-indent indent-len)))
|
||||||
|
((string-suffix-p ":" cur-line)
|
||||||
|
(max (- prev-indent indent-len) 0))
|
||||||
|
(t prev-indent))))))
|
||||||
|
|
||||||
|
;;; TODO: customizable indentation (amount of spaces, tabs, etc)
|
||||||
|
(defun simpc-indent-line ()
|
||||||
|
(interactive)
|
||||||
|
(when (not (bobp))
|
||||||
|
(let* ((desired-indentation
|
||||||
|
(simpc--desired-indentation))
|
||||||
|
(n (max (- (current-column) (current-indentation)) 0)))
|
||||||
|
(indent-line-to desired-indentation)
|
||||||
|
(forward-char n))))
|
||||||
|
|
||||||
|
(define-derived-mode simpc-mode prog-mode "Simple C"
|
||||||
|
"Simple major mode for editing C files."
|
||||||
|
:syntax-table simpc-mode-syntax-table
|
||||||
|
(setq-local font-lock-defaults '(simpc-font-lock-keywords))
|
||||||
|
(setq-local indent-line-function 'simpc-indent-line)
|
||||||
|
(setq-local comment-start "// "))
|
||||||
|
|
||||||
|
(provide 'simpc-mode)
|
||||||
53
sync.sh
53
sync.sh
@@ -84,12 +84,56 @@ copy_file() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sync_emacs_dir() {
|
||||||
|
local src_base="$1"
|
||||||
|
local dest_base="$2"
|
||||||
|
local action="$3"
|
||||||
|
|
||||||
|
# Files to sync
|
||||||
|
local files=("custom.el" "init.el")
|
||||||
|
# Directories to sync (cleared first)
|
||||||
|
local dirs=("lisp" "themes")
|
||||||
|
|
||||||
|
# Sync individual files
|
||||||
|
for file in "${files[@]}"; do
|
||||||
|
local src="$src_base/$file"
|
||||||
|
local dest="$dest_base/$file"
|
||||||
|
if [[ -f "$src" ]]; then
|
||||||
|
ensure_dir "$dest_base"
|
||||||
|
cp "$src" "$dest"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Sync directories (clear destination first)
|
||||||
|
for dir in "${dirs[@]}"; do
|
||||||
|
local src_dir="$src_base/$dir"
|
||||||
|
local dest_dir="$dest_base/$dir"
|
||||||
|
if [[ -d "$src_dir" ]]; then
|
||||||
|
# Clear destination directory
|
||||||
|
if [[ -d "$dest_dir" ]]; then
|
||||||
|
rm -rf "$dest_dir"
|
||||||
|
fi
|
||||||
|
# Copy directory
|
||||||
|
cp -r "$src_dir" "$dest_dir"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
push_dotfiles() {
|
push_dotfiles() {
|
||||||
echo "Pushing dotfiles from repo to home directory..."
|
echo "Pushing dotfiles from repo to home directory..."
|
||||||
|
|
||||||
|
# Handle .emacs.d specially (clear folders before syncing)
|
||||||
|
if [[ -d "$DOTFILES_DIR/.emacs.d" ]]; then
|
||||||
|
sync_emacs_dir "$DOTFILES_DIR/.emacs.d" "$HOME_DIR/.emacs.d" "Push"
|
||||||
|
fi
|
||||||
|
|
||||||
local count=0
|
local count=0
|
||||||
while IFS= read -r src_file; do
|
while IFS= read -r src_file; do
|
||||||
rel_path="${src_file#$DOTFILES_DIR/}"
|
rel_path="${src_file#$DOTFILES_DIR/}"
|
||||||
|
# Skip .emacs.d files (handled above)
|
||||||
|
if [[ "$rel_path" == .emacs.d/* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
dest_file="$(get_system_path "$rel_path")"
|
dest_file="$(get_system_path "$rel_path")"
|
||||||
copy_file "$src_file" "$dest_file" "Push"
|
copy_file "$src_file" "$dest_file" "Push"
|
||||||
((count++))
|
((count++))
|
||||||
@@ -101,9 +145,18 @@ push_dotfiles() {
|
|||||||
pull_dotfiles() {
|
pull_dotfiles() {
|
||||||
echo "Pulling dotfiles from home directory to repo..."
|
echo "Pulling dotfiles from home directory to repo..."
|
||||||
|
|
||||||
|
# Handle .emacs.d specially (clear folders before syncing)
|
||||||
|
if [[ -d "$HOME_DIR/.emacs.d" ]]; then
|
||||||
|
sync_emacs_dir "$HOME_DIR/.emacs.d" "$DOTFILES_DIR/.emacs.d" "Pull"
|
||||||
|
fi
|
||||||
|
|
||||||
local count=0
|
local count=0
|
||||||
while IFS= read -r dest_file; do
|
while IFS= read -r dest_file; do
|
||||||
rel_path="${dest_file#$DOTFILES_DIR/}"
|
rel_path="${dest_file#$DOTFILES_DIR/}"
|
||||||
|
# Skip .emacs.d files (handled above)
|
||||||
|
if [[ "$rel_path" == .emacs.d/* ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
src_file="$(get_system_path "$rel_path")"
|
src_file="$(get_system_path "$rel_path")"
|
||||||
copy_file "$src_file" "$dest_file" "Pull"
|
copy_file "$src_file" "$dest_file" "Pull"
|
||||||
((count++))
|
((count++))
|
||||||
|
|||||||
Reference in New Issue
Block a user