diff --git a/custom.el b/custom.el index c39d07f..881dc58 100644 --- a/custom.el +++ b/custom.el @@ -9,7 +9,8 @@ exec-path-form-shell gcmh hungry-delete marginalia multiple-cursors orderless restart-emacs smart-mode-line solarized-theme vertico)) '(safe-local-variable-values - '((eval progn + '((gptel-mode . t) + (eval progn (setq org-hugo-base-dir (if (eq system-type 'windows-nt) "h:/emacs/hugo/this-is-my-blog/" "~/org/hugo/this-is-my-blog/")) diff --git a/init.el b/init.el index 845ea53..a89c2d2 100644 --- a/init.el +++ b/init.el @@ -23,6 +23,7 @@ (require 'init-window) (require 'init-exwm) (require 'init-dired) +(require 'init-gptel) (require 'init-workspace) (require 'init-ui) (require 'init-kbd) diff --git a/lisp/init-completion.el b/lisp/init-completion.el index 32da7a5..611e9d6 100644 --- a/lisp/init-completion.el +++ b/lisp/init-completion.el @@ -7,11 +7,19 @@ ;; eglot (use-package eglot :hook ((python-mode . eglot-ensure) - (scheme-mode . eglot-ensure)) + ;; (scheme-mode . eglot-ensure) + ) :config (setq eglot-send-changes-idle-time 0.25) (add-to-list 'eglot-server-programs - '(scheme-mode . ("guile-lsp-server")))) + '(scheme-mode . ("guile-lsp-server"))) + + (add-hook 'eglot-managed-mode-hook ;; 在scheme模式禁用eglot补全,保留其他功能 + (lambda () + (when (derived-mode-p 'scheme-mode) + (setq-local completion-at-point-functions + (remq 'eglot-completion-at-point + completion-at-point-functions)))))) ;; corfu (use-package corfu @@ -31,11 +39,10 @@ gud-mode vterm-mode) t)) - :hook ((global-corfu-mode . corfu-popupinfo-mode) - (global-corfu-mode . corfu-history-mode)) - - :init (global-corfu-mode) - + :init + (global-corfu-mode) + (corfu-popupinfo-mode) + (corfu-history-mode) :config (add-hook 'after-init-hook #'global-corfu-mode) ;;Quit completion before saving @@ -119,13 +126,13 @@ (global-treesit-auto-mode) (setq treesit-font-lock-level 4)) -(use-package geiser) +(use-package geiser + :config + (with-eval-after-load 'geiser + (setq geiser-default-implementation 'guile))) (use-package geiser-guile) -(with-eval-after-load 'geiser - (setq geiser-default-implementation 'guile)) - (provide 'init-completion) ;;; init-completion.el ends here diff --git a/lisp/init-gptel.el b/lisp/init-gptel.el new file mode 100644 index 0000000..0ceb57b --- /dev/null +++ b/lisp/init-gptel.el @@ -0,0 +1,98 @@ +;;; init-gptel.el --- ai -*- lexical-binding: t -*- + +;;; Commentary: + +;;; Code: + +(use-package gptel + :config + (setq gptel-default-mode 'org-mode) + + + (defun my/org-auto-gptel () + (when (derived-mode-p 'org-mode) + (save-excursion + (goto-char (point-min)) + (when (re-search-forward "^#\\+GPTEL_MODEL:" nil t) + (gptel-mode))))) + (add-hook 'org-mode-hook #'my/org-auto-gptel) + + (add-hook 'gptel-post-response-functions 'gptel-end-of-response) + (add-hook 'gptel-post-stream-hook 'gptel-auto-scroll) + + (setq gptel-prompt-prefix-alist '((markdown-mode . "### ") (org-mode . "** User: ") (text-mode . "### "))) + + ;; 读取文件 + (gptel-make-tool + :function (lambda (filepath) + (with-temp-buffer + (insert-file-contents (expand-file-name filepath)) + (buffer-string))) + :name "read_file" + :description "Read and display the contents of a file" + :args '((:name "filepath" :type string :description "Path to the file")) + :category "filesystem") + + ;; 创建文件 + (gptel-make-tool + :name "create_file" ; javascript-style snake_case name + :function (lambda (path filename content) ; the function that runs + (let ((full-path (expand-file-name filename path))) + (with-temp-buffer + (insert content) + (write-file full-path)) + (format "Created file %s in %s" filename path))) + :description "Create a new file with the specified content" + :args (list '(:name "path" ; a list of argument specifications + :type string + :description "The directory where to create the file") + '(:name "filename" + :type string + :description "The name of the file to create") + '(:name "content" + :type string + :description "The content to write to the file")) + :category "filesystem") ; An arbitrary label for grouping + + + (gptel-make-tool + :name "read_buffer" ; javascript-style snake_case name + :function (lambda (buffer) ; the function that will run + (unless (buffer-live-p (get-buffer buffer)) + (error "error: buffer %s is not live." buffer)) + (with-current-buffer buffer + (buffer-substring-no-properties (point-min) (point-max)))) + :description "return the contents of an emacs buffer" + :args (list '(:name "buffer" + :type string ; :type value must be a symbol + :description "the name of the buffer whose contents are to be retrieved")) + :category "emacs") ; An arbitrary label for grouping + + (gptel-make-openai "Kimi-Code" + :host "api.kimi.com" + :endpoint "/coding/v1/chat/completions" + :protocol "https" + :key (lambda () + (auth-source-pick-first-password :host "api.kimi.com" :user "apikey")) + :stream t + :models '(kimi-for-coding) + :header (lambda (_) + (when-let ((key (gptel--get-api-key))) + `(("User-Agent" . "RooCode/3.30.3") + ("HTTP-Referer" . "https://github.com/RooVetGit/Roo-Cline") + ("X-Title" . "Roo Code") + ("Authorization" . ,(concat "Bearer " key)))))) + + (with-eval-after-load 'gptel + (setf gptel--system-message + "You are a large language model living in Emacs and a helpful assistant. Respond concisely. +- NEVER use unescaped org-mode headings. Lines MUST NOT begin with `* `, `** `, `*** `, etc. If you must start a line with asterisks, use the standard org escape format `,*` (e.g. `,* Heading`, `,** Sub-heading`)."))) + +(use-package gptel-agent + :config + (add-to-list 'gptel-agent-dirs "~/.emacs.d/lisp/" t) + (gptel-agent-update)) + +(provide 'init-gptel) + +;;; init-gptel.el ends here diff --git a/lisp/init-kbd.el b/lisp/init-kbd.el index 0246c9f..033722a 100644 --- a/lisp/init-kbd.el +++ b/lisp/init-kbd.el @@ -446,6 +446,14 @@ Disable jinx-mode if it's enable and global-jinx-mode is disable , otherwise tog (define-key persp-mode-map (kbd "C-c p c") nil) (global-set-key (kbd "C-c p d") 'persp-kill) +;; gptel +(general-def + :prefix "C-c g" + "o" 'gptel + "m" 'gptel-menu + "s" 'gptel-send + "a" 'gptel-agent) + (provide 'init-kbd) ;;; init-kbd.el ends here diff --git a/lisp/init-startup.el b/lisp/init-startup.el index 81be898..2f5af84 100644 --- a/lisp/init-startup.el +++ b/lisp/init-startup.el @@ -71,8 +71,7 @@ (setq-default frame-title-format '("%b - Emacs")) ;; electirc-pair-mode -(add-hook 'emacs-lisp-mode-hook 'electric-pair-mode) -(add-hook 'org-mode-hook 'electric-pair-mode) +(add-hook 'org-mode-hook 'electric-pair-local-mode) ;; short anwser (if (boundp 'use-short-answers) diff --git a/lisp/init-ui.el b/lisp/init-ui.el index ccd2a9d..05c1da4 100644 --- a/lisp/init-ui.el +++ b/lisp/init-ui.el @@ -67,13 +67,13 @@ ;; ;; sml/theme 'respectful) ;; (sml/setup)) -(use-package simple-modeline - :init (simple-modeline-mode) - :config - ;; (defun simple-modeline-segment-buffer-name () - ;; "Displays the full path of current file in the mode-line." - ;; (propertize " %f" 'face 'mode-line-buffer-id)) - ) +;; (use-package simple-modeline +;; :init (simple-modeline-mode) +;; :config +;; ;; (defun simple-modeline-segment-buffer-name () +;; ;; "Displays the full path of current file in the mode-line." +;; ;; (propertize " %f" 'face 'mode-line-buffer-id)) +;; ) ;; eshell高亮 (use-package eshell-syntax-highlighting diff --git a/lisp/init-window.el b/lisp/init-window.el index 7a6123b..f5d0536 100644 --- a/lisp/init-window.el +++ b/lisp/init-window.el @@ -28,6 +28,9 @@ "\\*Edit Annotation.*\\*" "\\*Flutter\\*" "\\*Ibuffer\\*" + "\\*Geiser Debug\\*" + "\\*Kimi-Code\\*" + "\\*OpenRouter\\*" bookmark-bmenu-mode lsp-bridge-ref-mode comint-mode @@ -41,6 +44,7 @@ ivy-occur-mode ivy-occur-grep-mode process-menu-mode list-environment-mode cargo-process-mode youdao-dictionary-mode osx-dictionary-mode fanyi-mode + gptel-mode "^\\*eshell.*\\*.*$" eshell-mode "^\\*shell.*\\*.*$" shell-mode