From 6d93711cc1a893bf9d281814d3642d6d59ed9bb9 Mon Sep 17 00:00:00 2001 From: alisonlai Date: Wed, 10 Jul 2024 13:51:13 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20update=20golang?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- chatgpt/emacs.org | 71 ++++++++++++ chatgpt/golang.org | 150 +++++++++++++++++++++++++ chatgpt/redis.org | 19 ++++ lisp/init-copilot-local.el | 32 ++++-- lisp/init-golang-local.el | 210 +++++++++++++++++++++++------------ lisp/init-local.el | 2 + lisp/init-lsp-mode-local.el | 31 +++++- lisp/init-undo-tree-local.el | 8 +- 8 files changed, 441 insertions(+), 82 deletions(-) create mode 100644 chatgpt/redis.org diff --git a/chatgpt/emacs.org b/chatgpt/emacs.org index 1280d1eb32..b76fdbd7ad 100644 --- a/chatgpt/emacs.org +++ b/chatgpt/emacs.org @@ -92,3 +92,74 @@ org-mode 是一个 Emacs 的 major mode,用于处理文本和笔记。org-mode = 这将把所有备份文件保存到 ~/backup 目录中。 + +* golang 和 gptel +(defun maple/go-auto-comment () + "Automatically add comments to Go code using gocmt and GPTel." + (interactive) + (let ((gocmt-command (concat "gocmt -i " buffer-file-name))) + (shell-command-on-region (point-min) (point-max) gocmt-command) + ;; 使用 GPTel 包生成评论 + (let ((comment-prompt (concat "Please add comments to the following Go code:\n\n" + (buffer-substring-no-properties (point-min) (point-max))))) + (gptel-send + comment-prompt + (lambda (response) + (save-excursion + (goto-char (point-max)) + (insert "\n\n" response))))))) +这段代码每行作用是 + +这段代码为 Emacs 中的一个函数,用于自动向 Go 代码中添加注释。具体来说: + +- 第一行定义了一个名为 "maple/go-auto-comment" 的函数。 +- 第二行使用 "interactive" 声明该函数可以被用户交互调用。 +- 第三行定义了一个变量 "gocmt-command",用于指定调用 "gocmt" 命令的完整字符串,其中 "-i" 表示直接修改文件而不是输出到终端。 +- 第四行使用 "shell-command-on-region" 函数运行 "gocmt-command" 命令,将文件从缓冲区的第一行到最后一行传递给它。 + 它将使用 "gocmt" 命令自动添加注释。 +- 第七行创建一个名为 "comment-prompt" 的变量,用于在 GPTel 包中使用的评论提示信息。它将文件从缓冲区中的第一行到最后一行传递给它。 +- 第八行使用 "gptel-send" 函数(需要事先加载 GPTel 包)向 GPT 自然语言处理系统发送 "comment-prompt",并在回调中接收 GPT 的响应。 +- 第九行使用 "save-excursion" 函数保存当前光标位置,然后将响应插入到缓冲区最后一行的下方,以添加注释。 + + comment-prompt 是什么内容 + +"comment-prompt" 是一个字符串变量,用于在 GPTel 包中使用的一个评论提示信息。在这里,它被设置为一个多行字符串,其中包含两条消息: +- 请将注释添加到以下 Go 代码中。 +- 在字符串的最后,将缓冲区中的代码插入到字符串中,以便将其发送到 GPT 接口。其目的是向 GPT 提供更好的上下文信息,让其能够更好地理解并生成相关的注释内容。 + + 添加日志,打印comment-prompt和gpt返回的response + +修改函数代码如下,添加了 =message= 函数用于在 minibuffer 中输出日志: + +#+begin_src +(defun maple/go-auto-comment () + "Automatically add comments to Go code using gocmt and GPTel." + (interactive) + (let ((gocmt-command (concat "gocmt -i " buffer-file-name)) + (comment-prompt (concat "Please add comments to the following Go code:\n\n" + (buffer-substring-no-properties (point-min) (point-max))))) + (shell-command-on-region (point-min) (point-max) gocmt-command) + ;; 使用 GPTel 包生成评论 + (gptel-send + comment-prompt + (lambda (response) + (message "comment-prompt: %s\ngpt-response: %s" comment-prompt response) + (save-excursion + (goto-char (point-max)) + (insert "\n\n" response)))))) + +#+end_src + +它会在函数执行时输出 =comment-prompt= 和 =gpt-response= 到 minibuffer 中。 + +- helm-M-x-execute-command: Wrong number of arguments: (0 . 1), 2 + +这个错误通常发生在使用 Helm 插件的 M-x 命令时。它表示给函数传递的参数数量不正确。具体而言,它需要一个参数 (0 . 1),但是传递了不同数量的参数。 + +这可能是由于以下一些情况所致: + +1. 版本不兼容:这个错误可能是由不同版本的 Helm 和 Emacs 之间的不兼容性引起的。尝试升级或降级 Helm 插件和 Emacs 版本来解决此问题。 + +2. 配置错误:这个错误也可能由 Helm 配置错误引起的。请确保你正确配置并加载了 Helm 插件。 + +3. 冲突插件:这个错误也可能是由其他插件与 Helm 插件的冲突引起的。尝试禁用其他插件并逐一排除问题以找到原因。 diff --git a/chatgpt/golang.org b/chatgpt/golang.org index 86ead7cbe4..04fb684bc2 100644 --- a/chatgpt/golang.org +++ b/chatgpt/golang.org @@ -38,3 +38,153 @@ func main() { #+begin_src error 1, error 2, error 3 #+end_src + + +* for 建议 + +片、字符串等序可以具列类型。建议使用以下方式遍历: + + #+begin_src go + for i, v :=体说说您需要关于 for 循环的哪些方面的建议吗? + +在 Golang 中,for 有多种用法,不同的用法适用于不同的场景。以下是一些 for 循环的常见用法及其建议: + +1. 遍历数组、切片、字符串: + + 在 Golang 中,for 可以用于遍历数组、切片、字符串等序可以具列类型。建议使用以下方式遍历: + + #+begin_src go + for i, v := range arr { + // i 表示当前元素的下标,v 表示当前元素的值 + // 具体操作 + } + #+end_src + + 其中,=i= 表示当前元素的下标,=v= 表示当前元素的值。使用 =range= 关键字可以让循环自动的处理序列中的每个元素。 + +2. 遍历 map: + + 在 Golang 中,for 可以用于遍历 map。建议使用以下方式遍历: + + #+begin_src go + for k, v := range m { + // k 表示当前键,v 表示当前值 + // 具体操作 + } + #+end_src + + 其中,=k= 表示当前键,=v= 表示当前值。同样使用 =range= 关键字,循环每次会返回 map 中的键和值。 + +3. 死循环: + + 在需要无限循环的操作中,可以使用 for 无限循环。建议使用以下方式: + + #+begin_src go + for { + // 具体操作 + } + #+end_src + + 无限循环可以通过 break 来跳出。 + +4. 遍历通道(channel): + + 在 Golang 中,for 可以用于遍历通道。建议使用以下方式遍历: + + #+begin_src go + for v := range ch { + // v 表示当前通道中的值 + // 具体操作 + } + #+end_src + + 在通道关闭前,for 循环会一直等待通道中的值。 + +5. 常规循环: + + 在需要常规做 n 次循环操作,建议使用以下方式: + + #+begin_src go + for i := 0; i < n; i++ { + // 具体操作 + } + #+end_src + + 其中,i 从 0 开始取,每次执行后加 1,循环 n 次。 + +这些都是常见的 for 循环用法,具体用哪种方式要根据实际需求来决定。 + + +* slog 用法 + +=slog= 是一个简单的日志库,可以很方便地在 Golang 代码中记录和输出日志信息。它提供了一个比较方便的 API 以及不同级别的日志输出。以下是 slog 的基本使用方法: + +1. 导入 slog 包及其依赖: + + #+begin_src go + import ( + "github.com/slclub/slog" + ) + #+end_src + +2. 初始化日志: + + #+begin_src go + func main() { + // 初始化 slogs,第一个参数表示日志级别 + slog.Init(slog.LevelDebug) + + // 记录日志 + } + #+end_src + +3. 记录日志: + + #+begin_src go + slog.Debug("debug message") + slog.Info("info message") + slog.Warn("warn message") + slog.Error("error message") + #+end_src + + slog 提供了不同级别的日志输出,支持的级别包括 Debug、Info、Warn、Error、Fatal、Panic。=Error= 级别以上的日志会写入到文件中。 + +4. 配置输出样式: + + slog 支持通过 =slog.SetFormat= 方法来设置输出样式。默认格式是: + + #+begin_src txt + 2021/10/21 11:54:00 [Debug] this is a debug message + #+end_src + + 可以通过以下代码来自定义输出格式: + + #+begin_src go + slog.SetFormat(`[${LEVEL}] ${DATE} ${TIME} ${FILE}(${LINE})\n${MESSAGE}\n`) + #+end_src + + 其中,=${LEVEL}= 表示日志级别,=${DATE}= 表示日期,=${TIME}= 表示时间,=${FILE}= 表示文件名,=${LINE}= 表示行号,=${MESSAGE}= 表示日志内容。 + +除了以上的基本用法,slog 还有很多附加功能,比如可以输出到控制台和文件、支持同时输出多个日志、支持日志轮转等。更多详细信息可以参考 slog 的文档:https://github.com/slclub/slog + +- slog.Error("fail", "msg fail", "err", err.Error()) 这里面 "fail", "msg fail", "err", err.Error() 分别代表什么 + +在 slog.Error 方法中,"fail"、"msg fail"、"err" 和 err.Error() 分别代表以下含义: + +- "fail" 是 slog.Error 方法的第一个参数,表示错误的信息。 +- "msg fail" 是 slog.Error 方法的中间参数,表示错误信息的附加说明。 +- "err" 是 slog.Error 方法的一个键值对,用来存储和记录错误相关的信息。 +- err.Error() 是 slog.Error 方法的一个键值对,表示具体的错误信息。 + +在 slog 中,使用键值对的方式存储错误信息,这样可以更方便地查看和记录错误的详细信息。例如,err 可以用来记录错误的文件名、行号等相关信息。 + +- slog.Info("fail", "msg fail", "err", err.Error()) 这里面 "fail", "msg fail", "err", err.Error() 分别代表什么 + +在 slog.Info 方法中,"fail"、"msg fail"、"err" 和 err.Error() 分别代表以下含义: + +- "fail" 是 slog.Info 方法的第一个参数,表示信息的内容。 +- "msg fail" 是 slog.Info 方法的中间参数,用来记录信息的附加说明。 +- "err" 是 slog.Info 方法的一个键值对,用来存储和记录和信息相关的错误信息。 +- err.Error() 是 slog.Info 方法的一个键值对,表示具体的错误信息。 + +与 slog.Error 方法类似,slog.Info 方法也使用键值对来存储相关信息,使得日志记录更加方便和详细。例如,err 可以用来记录写入日志的源代码文件名、行号等信息。 diff --git a/chatgpt/redis.org b/chatgpt/redis.org new file mode 100644 index 0000000000..106def6886 --- /dev/null +++ b/chatgpt/redis.org @@ -0,0 +1,19 @@ +* Redis Incr 怎么设置过期时间 + +Redis 的 =INCR= 命令只能增加一个 Key 对应的值,而不能设置过期时间。如果需要一个具有过期时间的计数器,可以使用 =SETEX= 命令来设置一个带过期时间的 Key,然后结合 =INCR= 命令来实现计数器功能,例如: + +#+begin_src +SETEX my_counter 3600 0 # 有效期为 1 小时,计数器初始值为 0 +#+end_src + +每次需要增加计数器的值时,可以使用 INCR 命令: + +#+begin_src +INCR my_counter +#+end_src + +注意,设置的时间单位为秒,如果需要设置其他时间单位,可以使用多个参数,例如: + +#+begin_src +SETEX my_counter 60m 0 # 有效期为 60 分钟,计数器初始值为 0 +#+end_src diff --git a/lisp/init-copilot-local.el b/lisp/init-copilot-local.el index ca4816d8c3..c6c62a3723 100644 --- a/lisp/init-copilot-local.el +++ b/lisp/init-copilot-local.el @@ -1,27 +1,45 @@ -;;; init-copilot-local --- Support copilot +;;; init-copilot-local.el --- Support copilot ;;; Commentary: ;;; Code: (add-to-list 'load-path - (expand-file-name (concat user-emacs-directory "lisp/copilot.el"))) + (expand-file-name (concat user-emacs-directory "lisp/copilot.el"))) (require 'copilot) -;; copilot automatically provide completions + +;; Copilot automatically provide completions (add-hook 'prog-mode-hook 'copilot-mode) -; complete by copilot first, then auto-complete +;; Complete by copilot first, then auto-complete (defun my-tab () (interactive) (or (copilot-accept-completion) (ac-expand nil))) (with-eval-after-load 'auto-complete - ; disable inline preview + ;; Disable inline preview (setq ac-disable-inline t) - ; show menu if have only one candidate + ;; Show menu if have only one candidate (setq ac-candidate-menu-min 0)) - + +(setq copilot-max-characters 1000000) ;; 增大为 1,000,000 + (define-key copilot-completion-map (kbd "") 'copilot-accept-completion) (define-key copilot-completion-map (kbd "TAB") 'copilot-accept-completion) +;; Bind `my-tab` function to TAB key in prog-mode +(add-hook 'prog-mode-hook + (lambda () + (local-set-key (kbd "TAB") 'my-tab) + (local-set-key (kbd "") 'my-tab))) + +(defun maybe-disable-copilot () + "Disable Copilot if the buffer is too large." + (when (> (buffer-size) copilot-max-characters) + (copilot-mode -1) + (message "Copilot disabled due to large buffer size."))) + +(add-hook 'copilot-mode-hook 'maybe-disable-copilot) + + (provide 'init-copilot-local) ;;; init-copilot-local.el ends here diff --git a/lisp/init-golang-local.el b/lisp/init-golang-local.el index e807bd78a0..24a01e3d15 100644 --- a/lisp/init-golang-local.el +++ b/lisp/init-golang-local.el @@ -2,86 +2,156 @@ ;;; Commentary: ;;; Code: -(require-package 'go-mode) -(require-package 'go-tag) -(require-package 'go-stacktracer) -(require-package 'go-errcheck) -(require-package 'go-fill-struct) -(require-package 'go-impl) -(require-package 'go-imports) -(require-package 'go-guru) -(require-package 'go-eldoc) -(require-package 'go-gen-test) -(require-package 'gotest) -(require-package 'go-projectile) -(require-package 'golint) -(require-package 'go-gopath) -(require-package 'flycheck-golangci-lint) -(require-package 'flycheck-gometalinter) -(require-package 'go-dlv) -(require-package 'gorepl-mode) - -(ac-config-default) -(when (memq window-system '(mac ns x)) - (exec-path-from-shell-initialize)) - -(global-flycheck-mode) -(with-eval-after-load 'go-mode - (autoload 'flycheck-get-checker-for-buffer "golint") - (autoload 'flycheck-get-checker-for-buffer "govet") - (autoload 'flycheck-get-checker-for-buffer "flycheck")) - -(setq flycheck-golangci-lint-config "~/.emacs.d/conf/.golangci.yml") -(setq flycheck-golangci-lint-deadline "10m") -(eval-after-load 'flycheck - '(add-hook 'go-mode-hook #'flycheck-golangci-lint-setup)) - -(setq flycheck-gometalinter-vendor t) -(setq flycheck-gometalinter-enable-linters '("golangci-lint")) -(setq flycheck-gometalinter-deadline "10s") -(setq flycheck-gometalinter-config "~/.emacs.d/config/.gometalinter-config.json") - -(add-hook 'go-mode-hook '(lambda () - (local-set-key (kbd "C-c C-r") 'go-remove-unused-imports) - (local-set-key (kbd "C-c C-g") 'go-goto-imports) - (local-set-key (kbd "C-c C-f") 'gofmt) - (local-set-key (kbd "C-c C-k") 'godoc))) - -(setq gofmt-command "goimports") -(setq gofmt-args '("-local" "git.code.oa.com")) +(require 'package) + +(eval-when-compile + (require 'use-package)) + +;; 配置 Go 相关包 +(use-package go-mode + :ensure t + :hook ((before-save . my-gofmt-and-goimports) + (go-mode . gorepl-mode) + (go-mode . go-eldoc-setup) + (go-mode . go-guru-hl-identifier-mode)) + :bind (("C-c C-r" . go-remove-unused-imports) + ("C-c C-g" . go-goto-imports) + ("C-c C-f" . gofmt) + ("C-c C-k" . godoc)) + :config + (setq gofmt-command "goimports")) + +(use-package go-tag + :ensure t + :bind (("C-c t" . go-tag-add) + ("C-c s" . alison-go-tag-add) + ("C-c T" . go-tag-remove)) + :config + (setq go-tag-args (list "-transform" "snakecase"))) + +(use-package flycheck + :ensure t + :init (global-flycheck-mode) + :config + (setq flycheck-golangci-lint-config "~/.emacs.d/conf/.golangci.yml" + flycheck-golangci-lint-deadline "10m" + flycheck-gometalinter-vendor t + flycheck-gometalinter-enable-linters '("golangci-lint") + flycheck-gometalinter-deadline "10s" + flycheck-gometalinter-config "~/.emacs.d/config/.gometalinter-config.json") + (eval-after-load 'flycheck + '(add-hook 'go-mode-hook #'flycheck-golangci-lint-setup))) + +(use-package go-gen-test + :ensure t) + +(use-package gotest + :ensure t + :config + (setq go-test-args "-gcflags=all=-l")) + +(use-package go-dlv + :ensure t) + +(use-package gorepl-mode + :ensure t + :hook (go-mode . gorepl-mode)) + +(use-package go-eldoc + :ensure t + :hook (go-mode . go-eldoc-setup)) + +(use-package go-guru + :ensure t + :hook (go-mode . go-guru-hl-identifier-mode)) + +(use-package go-stacktracer + :ensure t) + +(use-package go-fill-struct + :ensure t) + +(use-package go-impl + :ensure t) + +(use-package go-imports + :ensure t) + +(use-package golint + :ensure t) + +(use-package go-gopath + :ensure t) + +(use-package flycheck-golangci-lint + :ensure t) + +(use-package flycheck-gometalinter + :ensure t) + +(defun my-gofmt-s-r () + "Run gofmt with -s and -r 'interface{} -> any' on the current buffer if it's a Go file." + (when (eq major-mode 'go-mode) + (shell-command-to-string (format "gofmt -s -r 'interface{} -> any' -w %s" (buffer-file-name))) + (revert-buffer t t t))) + +(defun my-gofmt-and-goimports () + "Run gofmt with -s and -r 'interface{} -> any', then run goimports if it's a Go file." + (when (eq major-mode 'go-mode) + (my-gofmt-s-r) + (gofmt))) (defun run-go-mod-tidy () - "Run `go mod tidy` in the current project." - (when (string-equal major-mode 'go-mode) - (shell-command "go mod tidy"))) + "Run `go mod tidy` synchronously in the current project if it's a Go file." + (when (eq major-mode 'go-mode) + (let ((default-directory (file-name-directory buffer-file-name))) + (call-process "go" nil nil nil "mod" "tidy")))) -(add-hook 'before-save-hook 'gofmt-before-save) -(add-hook 'before-save-hook 'run-go-mod-tidy) -(setq go-test-args "-gcflags=all=-l") -(defun maple/go-auto-comment() + +;; (defun maple/go-auto-comment () +;; "Automatically add comments to Go code using gocmt and GPTel." +;; (interactive) +;; (let ((gocmt-command (concat "gocmt -i " buffer-file-name))) +;; (shell-command-on-region (point-min) (point-max) gocmt-command) +;; ;; Call gptel-send-region to generate comments using GPT +;; (gptel-send-region (point-min) (point-max)))) + + +(defun maple/go-auto-comment () + "Automatically add comments to Go code using gocmt and GPTel." (interactive) - (setq gocmt (concat "gocmt -i " buffer-file-name)) - (shell-command-on-region (point-min) (point-max) gocmt)) + (let ((gocmt-command (concat "gocmt -i " buffer-file-name))) + (shell-command-on-region (point-min) (point-max) gocmt-command) + ;; 使用 GPTel 包生成评论 + (let ((comment-prompt (concat "Please add comments to the following Go code:\n\n" + (buffer-substring-no-properties (point-min) (point-max))))) + (gptel-send + comment-prompt + (lambda (response) + (message "comment-prompt: %s\ngpt-response: %s" comment-prompt response) + (save-excursion + (goto-char (point-max)) + (insert "\n\n" response))))))) + +;; 绑定函数到快捷键或添加到 Go 模式钩子中 +(add-hook 'go-mode-hook + (lambda () + (local-set-key (kbd "C-c C-c") 'maple/go-auto-comment))) + + -(setq go-tag-args (list "-transform" "snakecase")) (defun alison-go-tag-add (n) "Please select type for TRANSFORM." - (interactive "xSelect transform 1->base_domain 2->baseDomain 3->base-domain 4->BaseDomain:") - (setq selectForm (pcase n - (1 "snakecase") - (2 "camelcase") - (3 "lispcase") - (4 "keep"))) - (setq go-tag-args (list "-transform" selectForm))) - -(with-eval-after-load 'go-mode - (define-key go-mode-map (kbd "C-c t") #'go-tag-add) - (define-key go-mode-map (kbd "C-c s") #'alison-go-tag-add) - (define-key go-mode-map (kbd "C-c T") #'go-tag-remove)) + (interactive "nSelect transform 1->base_domain 2->baseDomain 3->base-domain 4->BaseDomain: ") + (setq go-tag-args (list "-transform" + (pcase n + (1 "snakecase") + (2 "camelcase") + (3 "lispcase") + (4 "keep"))))) (provide 'init-golang-local) ;;; init-golang-local.el ends here - diff --git a/lisp/init-local.el b/lisp/init-local.el index b235548077..5bf855df6d 100644 --- a/lisp/init-local.el +++ b/lisp/init-local.el @@ -2,6 +2,8 @@ ;;; Commentary: ;;; Code: + +(require-package 'use-package) (require 'init-super-save-local) (require 'init-auto-save-local) (require 'init-yasnippet-local) diff --git a/lisp/init-lsp-mode-local.el b/lisp/init-lsp-mode-local.el index 19fbee6e49..940a001ee2 100644 --- a/lisp/init-lsp-mode-local.el +++ b/lisp/init-lsp-mode-local.el @@ -9,6 +9,28 @@ (require-package 'helm-lsp) (require-package 'projectile) +;; 设置在需要时才启动 LSP +(defun my/lsp-init-on-demand () + "Initialize LSP mode on demand." + (when (and (buffer-file-name) + (buffer-live-p (current-buffer)) + (not (lsp-workspaces))) + (condition-case err + (lsp-deferred) + (error (message "Error initializing LSP: %s" (error-message-string err)))))) + +;; 在需要时启动 LSP +(dolist (hook '(find-file-hook)) + (add-hook hook 'my/lsp-init-on-demand)) + +;; 延迟恢复的缓冲区加载 +(setq desktop-restore-eager 5) + +;; 提高恢复速度 +(setq desktop-restore-frames nil) +(setq desktop-restore-reuses-frames t) + +;; 启动相应 mode 时启动 yasnippet (dolist (hook '(python-mode-hook c++-mode-hook c-mode-hook @@ -26,6 +48,7 @@ (add-hook hook #'lsp-deferred) (add-hook hook #'yas-minor-mode)) +;; 优化垃圾回收和进程输出读取 (setq gc-cons-threshold (* 100 1024 1024) read-process-output-max (* 1024 1024) treemacs-space-between-root-nodes nil @@ -41,7 +64,9 @@ (lsp-register-custom-settings '(("gopls.completeUnimported" t t) ("gopls.staticcheck" t t) - ("gopls.usePlaceholders" t t)))) + ("gopls.usePlaceholders" t t))) + (setq lsp-language-id-configuration (append lsp-language-id-configuration + '((emacs-lisp-mode . "emacs-lisp"))))) (lsp-treemacs-sync-mode t) @@ -57,10 +82,10 @@ (advice-add #'company-yasnippet :around #'company-yasnippet/disable-after-dot) -;; Ensure projectile is used to manage project switching +;; 确保 projectile 用于管理项目切换 (projectile-mode +1) -;; Track the previous project +;; 跟踪上一个项目 (defvar my/last-project nil) (defun my/switch-project-hook () diff --git a/lisp/init-undo-tree-local.el b/lisp/init-undo-tree-local.el index 08f35750c6..055c05ff0e 100644 --- a/lisp/init-undo-tree-local.el +++ b/lisp/init-undo-tree-local.el @@ -3,8 +3,12 @@ ;;; Code: (require-package 'undo-tree) -(setq undo-tree-history-directory-alist '(("." . "~/.emacs.d/undo"))) -(setq undo-tree-auto-save-history t) + +(setq undo-tree-history-directory-alist + `(("." . ,(concat user-emacs-directory "undo-tree-history")))) + +(setq undo-tree-auto-save-history nil) + (global-undo-tree-mode) (provide 'init-undo-tree-local) ;;; init-undo-tree-local.el ends here