;; Increase garbage collection threshold to accelerate startup
(setq gc-cons-threshold 64000000)
;; Set number of spaces for c/c++ source file
(setq c-basic-offset 2)
;; For a buffer-local variable, setq can only apply to current buffer,
;; while setq-default can apply to all buffers.
(setq-default tab-width 4)
;; Make the backspace properly erase the tab instead of
;; removing 1 space at a time.
(setq backward-delete-char-untabify-method 'hungry)
;; Prevent emacs from making backup files
(setq make-backup-files nil)
;; Set the default text coding system
(setq default-buffer-file-coding-system 'utf-8)
(prefer-coding-system 'utf-8)
;; Remove trailing whitespaces
(add-hook 'before-save-hook 'delete-trailing-whitespace)
(setq deleting-trailing-whitespace-switch t)
;; Toggle automatically deleting trailing whitespace
(defun toggle-deleting-trailing-whitespace ()
(interactive)
(if deleting-trailing-whitespace-switch
(progn
(remove-hook 'before-save-hook 'delete-trailing-whitespace)
(setq deleting-trailing-whitespace-switch nil)
(message "Toggle off delete-trailing-whitespace"))
(progn
(add-hook 'before-save-hook 'delete-trailing-whitespace)
(setq deleting-trailing-whitespace-switch t)
(message "Toggle on delete-trailing-whitespace"))))
(global-set-key (kbd "C-c w") 'toggle-deleting-trailing-whitespace)
;; Change TAB key behavior to insert spaces instead
(setq-default indent-tabs-mode nil)
;; More powerful automatic adjustments according to whitespace-style
;; variable, which may influence leading whitespaces.
;; (add-hook 'before-save-hook 'whitespace-cleanup)
;; Add a value to 'load-path'
(add-to-list 'load-path "~/.emacs.d/site-lisp")
(defun next-lines ()
(interactive)
(forward-line 5))
(defun previous-lines()
(interactive)
(forward-line -5))
(global-set-key (kbd "M-n") 'next-lines)
(global-set-key (kbd "M-p") 'previous-lines)
;; Revert buffer from disk
(defun refresh-file ()
(interactive)
(revert-buffer t (not (buffer-modified-p)) t))
(global-set-key (kbd "<f5>") 'refresh-file)
(global-set-key (kbd "C-x k") 'kill-this-buffer)
;; Coding mode configurations
(defun coding-mode ()
;; Highlight trailing whitespaces and exceeding part
;; when lines are longer than whitespace-line-column
(setq show-trailing-whitespace t)
;; If we want to tolerate projects with particularly long lines of code,
;; set the following variable to a bigger number.
;; (setq whitespace-line-column 200)
;; Auto-fill when current line is longer than 80 characters
(setq fill-column 80)
(setq auto-fill-function 'do-auto-fill)
(whitespace-mode t))
(defun add-multiple-hooks (hook-function hooks)
(mapc (lambda (hook) (add-hook hook hook-function)) hooks))
(add-multiple-hooks 'coding-mode
'(sh-mode-hook
c-mode-hook
c++-mode-hook
python-mode-hook))
(defun infer-indentation-style ()
;; if our source file uses tabs, we use tabs, if spaces spaces, and if
;; neither, we use the current indent-tabs-mode
(let ((space-count (how-many "^ " (point-min) (point-max)))
(tab-count (how-many "^\t" (point-min) (point-max))))
(if (> tab-count space-count)
(progn
(setq indent-tabs-mode nil)
(local-set-key (kbd "TAB") 'self-insert-command)
;; Indentation offset equals one TAB
(setq c-basic-offset 4)
;; We're changing the value of variable c-offsets-alist to change indentation behavior
;; Make substatement block following if/while
(c-set-offset 'substatement-open 0)
;; Make case statement indent
(c-set-offset 'case-label '+)
(message "infer indent-tabs-mode enabled")))))
(defun infer-trailing-whitespace-style ()
(setq disable-threshold 5)
(let ((trail-space-count (how-many " $" (point-min) (point-max))))
(if (> trail-space-count disable-threshold)
(toggle-deleting-trailing-whitespace))))
(add-hook 'c-mode-common-hook 'infer-indentation-style)
(add-hook 'c-mode-common-hook 'infer-trailing-whitespace-style)
;; Use y-n instead of yes-no
(fset 'yes-or-no-p 'y-or-n-p)
;; Display column number
(setq column-number-mode t)
;; Ignore ring-bell-function
(setq ring-bell-function 'ignore)
;; Put an newline at end of file if it doesn't exist
;; Newline character is regard as the end of each line, and
;; it may cause header file including error without it.
(setq require-final-newline t)
;; Highlight cursor line
(global-hl-line-mode t)
;; Remove tab-mark if TAB is generally used in a project.
(setq whitespace-style '(face tabs trailing lines space-before-tab
empty space-after-tab tab-mark))
(require 'package)
;; (setq package-archives '(("gnu" . "http://elpa.emacs-china.org/gnu/")
;; ("melpa" . "http://elpa.emacs-china.org/melpa/")
;; ("org" . "http://elpa.emacs-china.org/org/")))
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
;; Disable automatically loading after processing the init file
(setq package-enable-at-startup nil)
;; Avoid automatically adding (package-initialize) to the init file
(setq package--init-file-ensured t)
;; Install use-package
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
;; Enable use-package
(eval-when-compile
(require 'use-package))
;; Always download absent packages
(setq use-package-always-ensure t)
(require 'ibuffer)
(global-set-key (kbd "C-x C-b") 'ibuffer)
;; Define buffer groups
(setq ibuffer-saved-filter-groups
(quote (("default"
("dired" (mode . dired-mode))
("emacs" (or
(name . "^\\*scratch\\*$")
(name . "^\\*Help\\*$")
(name . "^\\*Messages\\*$")))
("programming" (or
(mode . python-mode)
(mode . c++-mode)
(mode . c-mode)
(mode . perl-mode)
(mode . python-mode)
(mode . emacs-lisp-mode)))
("shell" (or
(mode . sh-mode)
(mode . term-mode)
(mode . shell-mode)
(mode . eshell-mode)))
("edit" (or
(mode . org-mode)
(mode . markdown-mode)
(mode . text-mode)))
("git" (or
(mode . diff-mode)
(name . "^magit.*")
(name . ".gitignore")))
("gdb" (or
(mode . gdb-frames-mode)
(mode . gdb-inferior-io-mode)
(mode . gdb-breakpoints-mode)
(mode . gud-mode)
(mode . gdb-threads-mode)
(mode . gdb-locals-mode)))
("gnus" (or
(mode . message-mode)
(mode . bbdb-mode)
(mode . mail-mode)
(mode . gnus-group-mode)
(mode . gnus-summary-mode)
(mode . gnus-article-mode)
(name . "^\\.bbdb$")
(name . "^\\.newsrc-dribble")))))))
(add-hook 'ibuffer-mode-hook
(lambda ()
(ibuffer-switch-to-saved-filter-groups "default")))
;; Stop showing groups in which there is no buffer
(setq ibuffer-show-empty-filter-groups nil)
;; Hide the last two summary lines
(setq ibuffer-display-summary nil)
;; Do not ask for confirmation when deleting marked buffers
(setq ibuffer-expert t)
;; Use human readable Size column instead of original one
(define-ibuffer-column size-h
(:name "Size" :inline t)
(cond
((> (buffer-size) 1000000) (format "%7.1fM" (/ (buffer-size) 1000000.0)))
((> (buffer-size) 100000) (format "%7.0fk" (/ (buffer-size) 1000.0)))
((> (buffer-size) 1000) (format "%7.1fk" (/ (buffer-size) 1000.0)))
(t (format "%8d" (buffer-size)))))
;; Modify the default ibuffer-formats
(setq ibuffer-formats
'((mark modified read-only " "
(name 18 18 :left :nil)
" "
(size-h 9 -1 :right)
" "
(mode 16 16 :left :elide)
" "
filename-and-process)))
(use-package which-key)
(which-key-mode)
(use-package ace-window
:bind ("M-o" . 'ace-window)
:config
(setq aw-scope 'frame)
(setq aw-background nil)
(setq aw-dispatch-always t)
(setq aw-keys '(?a ?s ?d ?f ?g ?h ?j ?k ?l)))
(use-package command-log-mode)
(use-package undo-tree)
;; Prevent undo tree files from polluting your git repo
(setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo")))
;; C-/ undo; M-_ redo; C-x u visulaize.
(global-undo-tree-mode t)
(add-to-list 'auto-mode-alist '("\\.ic\\'" . c++-mode))
(add-to-list 'auto-mode-alist '("\\.yy\\'" . c++-mode))
(add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))
;; Syntax highlight for latest C++
(use-package modern-cpp-font-lock)
(add-hook 'c-mode-common-hook 'modern-c++-font-lock-global-mode)
;; Google c/c++ style
(use-package google-c-style)
(add-hook 'c-mode-common-hook 'google-set-c-style)
(add-hook 'c-mode-common-hook 'google-make-newline-indent)
;; Fold code block with `C-c @ C-c`
(add-hook 'c-mode-common-hook 'hs-minor-mode)
(use-package cmake-mode)
(add-to-list 'auto-mode-alist '("CMakeLists\\.txt\\'" . cmake-mode))
(add-to-list 'auto-mode-alist '("\\.cmake\\'" . cmake-mode))
(use-package flycheck)
(setq flycheck-clang-language-standard "c++11")
(use-package company)
(setq company-idle-delay 0)
(setq company-minimum-prefix-length 3)
(setq company-show-numbers t)
;; Popup the completion window manually
(global-set-key (kbd "C-c c") 'company-capf)
;; lsp-mode settings
;; NOTE: clangd cannot correctly find the references if the project directory is
;; under a symlinked parent directory. See https://github.com/clangd/clangd/issues/503
(defun init-lsp ()
"Load lsp-mode."
(use-package lsp-mode
:init (setq lsp-keymap-prefix "C-c l")
:custom (lsp-idle-delay 0.5)
(lsp-completion-provider :capf)
(lsp-enable-folding t)
(lsp-enable-snippet t)
(lsp-headerline-breadcrumb-enable nil)
(lsp-server-trace "verbose")
(lsp-clients-clangd-args
'("-j=32" "-background-index" "-log=verbose"
"-all-scopes-completion" "-suggest-missing-includes")))
(add-hook 'c-mode-common-hook #'lsp-deferred)
;; Don't collect completion symbols. If there are too many symbols in current file, will hang for seconds
(cl-defmethod my-xref-backend-identifier-completion-table ((_backend (eql xref-lsp)))
)
(advice-add 'xref-backend-identifier-completion-table :override #'my-xref-backend-identifier-completion-table)
;; Input symbol name to find the definition
(cl-defmethod my-xref-backend-identifier-at-point ((_backend (eql xref-lsp)))
(let ((thing (thing-at-point 'symbol)))
(and thing (propertize thing
'identifier-at-point t))))
(advice-add 'xref-backend-identifier-at-point :override #'my-xref-backend-identifier-at-point)
(cl-defmethod my-xref-backend-definitions ((_backend (eql xref-lsp)) identifier)
(save-excursion
(if (not (get-text-property 0 'identifier-at-point identifier))
(-if-let (pos (assoc identifier lsp--symbols-cache))
(progn (goto-char (cl-rest pos))
(lsp--locations-to-xref-items (lsp-request "textDocument/definition"
(lsp--text-document-position-params))))
(xref-backend-apropos _backend identifier))
(lsp--locations-to-xref-items (lsp-request "textDocument/definition"
(lsp--text-document-position-params))))))
(advice-add 'xref-backend-definitions :override #'my-xref-backend-definitions))
;; rtags settings
(defun init-rtags ()
"Load rtags."
(setq rtags-process-flags (concat "--rp-nice-value 10 "
"--job-count 8 "
"--error-limit 50000 "
"--log-file-log-level debug "
"--completion-logs"))
;; The hook will be called everytime we find definitions or references, causing multiple
;; emacs kill each other's rdm and launch its own, which is slow at startup. Not advised.
;; (add-hook 'c-mode-common-hook 'rtags-start-process-unless-running)
;;
;; Using the following command to keep a daemon rdm backend on the server. Multiple emacs clients can share it.
;; rdm --rp-nice-value 10 --job-count 8 --error-limit 50000 --log-file-log-level debug --completion-logs --daemon
(setq rtags-completions-enabled t)
(require 'rtags-xref)
(add-hook 'c-mode-common-hook #'rtags-xref-enable)
(require 'company)
(setq rtags-autostart-diagnostics t)
(rtags-diagnostics)
(setq rtags-completions-enabled t)
(push 'company-rtags company-backends)
(add-hook 'c-mode-common-hook 'company-mode)
(define-key c-mode-base-map (kbd "<C-tab>") (function company-complete)))
(defvar navigation-mode "lsp"
"The navigation mode used. It is either 'rtags' or 'lsp'.")
(cond ((equal navigation-mode "rtags")
(init-rtags))
((equal navigation-mode "lsp")
(init-lsp)))
;; Don't prompt if there's value at point for following functions
(setq xref-prompt-for-identifier '(not xref-find-definitions xref-find-references))
(use-package swiper
:bind (("C-s" . swiper)))
(use-package yasnippet)
(use-package yasnippet-snippets)
(use-package magit
:bind (("C-x g" . magit-status)
("C-o" . magit-diff-visit-file-other-window)))
(use-package ivy
:custom
(ivy-use-virtual-buffers t)
(ivy-count-format "%d/%d ")
(ivy-display-style 'fancy)
:config
(ivy-mode t))
(use-package counsel
:custom
(counsel-find-file-ignore-regexp "^#\\|/#\\|/\\.#\\|\\.(orig|rej)$\\|clangd.*\\(.idx\\)$")
:config
(counsel-mode t)
(require 'map)
;; ivy has a sort function list to provide sort method's to functions.
(map-put ivy-sort-functions-alist #'counsel-M-x #'string-lessp))
(use-package helm
:ensure t
:custom
(helm-split-window-inside-p t)
(helm-ff-file-name-history-use-recentf t)
:bind (("M-x" . 'helm-M-x)
("M-y" . 'helm-show-kill-ring)
("C-x C-f" . 'helm-find-files)
("C-x b" . 'helm-mini))
:config
(helm-autoresize-mode t)
(helm-mode t))
(define-key helm-map (kbd "C-z") 'helm-select-action) ; list actions using C-z
;; `C-c h m` run man
(global-set-key (kbd "C-c h") 'helm-command-prefix)
(global-unset-key (kbd "C-x c"))
;; Interactive search with ag(Silver Searcher)
(use-package helm-ag
:ensure t
;; `C-c C-f` follow search result mode
:bind (("C-c C-r" . 'helm-do-ag)
("C-c C-g" . 'helm-do-ag-project-root)))
(use-package projectile
:config
(projectile-mode +1)
(define-key projectile-mode-map (kbd "C-c p") 'projectile-command-map))
(use-package smartparens
:config
(smartparens-global-mode t)
(show-smartparens-global-mode t))
(use-package avy
:ensure t
:bind (("M-g w" . avy-goto-word-1)))
;; Enable mouse support
(add-hook 'gud-mode-hook (lambda ()
(setq gdb-show-main t)))
;; Conflict with tmux prefix C-t
(global-set-key (kbd "C-x C-a C-q") 'gud-tbreak)
;; smart-mode-line's dependency
(use-package rich-minority)
(require 'smart-mode-line)
(setq sml/no-confirm-load-theme t)
(setq sml/theme 'respectful)
(sml/setup)
;; View a file between different versions `M-x git-timemachine`
(use-package git-timemachine
:ensure t)
;; Predefine database configurations
(setq sql-connection-alist
'((local-test
(sql-product 'mysql)
(sql-server "127.0.0.1")
(sql-user "root")
(sql-password "")
(sql-database "test")
(sql-port 33332))))
(defun sql-connect-preset (name)
"Connect to a predefined SQL connection listed in `sql-connection-alist'"
(eval `(let ,(cdr (assoc name sql-connection-alist))
(flet ((sql-get-login (&rest what)))
(sql-product-interactive sql-product)))))
(defun mysql-local ()
(interactive)
(sql-connect-preset 'local-test))
;; Link the current buffer to client buffer
(defun mysqli-link()
(interactive)
(sql-mode)
(sql-set-product "mysql")
(sql-set-sqli-buffer))
(global-set-key (kbd "<f9>") 'mysql-local)
;; Load solarized theme
(add-to-list 'custom-theme-load-path
"~/.emacs.d/site-lisp/emacs-color-theme-solarized")
(load-theme 'solarized t)
(add-hook 'after-init-hook
(lambda ()
(if (display-graphic-p)
;; GUI
(set-frame-parameter nil 'background-mode 'light)
;; Terminal
(set-terminal-parameter nil 'background-mode 'dark))
(enable-theme 'solarized)))
(setq compilation-scroll-output 't)
;; Display colors normally in compilation output
(add-hook 'compilation-filter-hook 'ansi-color-compilation-filter)
(defun my-compile-func()
(interactive)
(if (vc-root-dir) (setq root-dir (vc-root-dir))
(setq root-dir default-directory))
(setq build-path-options '())
(setq build-path nil)
;; Find directory in which makefile exists
(let ((files (directory-files root-dir t "^build\\|^\\.")))
(dolist (direc-path files)
(if (file-exists-p (concat direc-path "/Makefile"))
(setq build-path-options (cons direc-path build-path-options)))))
(if (> (length build-path-options) 1)
(progn
;; Prompt user to select a choice from list
(setq build-path (completing-read "Choose directory to build: " build-path-options nil t)))
(if (= (length build-path-options) 1)
(setq build-path (car build-path-options)))) ;; Choose the first option in list
(if (not (null build-path))
(progn
(cd build-path)
(message "Makefile at %s" build-path)
(setq compile-command "make -j16"))
(setq compile-command (concat "g++ -std=c++11 -g " buffer-file-name)))
(compile compile-command))
(defun apg-compile-func()
(interactive)
(setq compile-command "brazil-build rebuild")
(compile compile-command)
(shell-command "python /local/home/zboli/tmp/test.py"))
(global-set-key (kbd "<f12>") 'apg-compile-func)
(global-set-key (kbd "<f10>") 'my-compile-func)