diff --git a/init.org b/init.org index 42d2c97..ef39f95 100644 --- a/init.org +++ b/init.org @@ -916,10 +916,11 @@ Use org-bullets for fancy headline markers Use typo-mode in org-mode for en and em dashes: #+begin_src emacs-lisp :tangle no -(require 'typo) - -(typo-global-mode 1) -(add-hook 'org-mode-hook 'typo-mode) +(use-package typo + :straight t + :hook (org-mode . typo-mode) + :config + (typo-global-mode 1)) #+end_src Use =org-fragtog= to show embedded LaTeX fragments when in insert mode. @@ -1373,6 +1374,22 @@ Enable =hs-minor-mode= in =prog-mode= to allow for folding away comments and mod #+end_src ** Copilot 😭 + +*** Copilot.el + +#+begin_src emacs-lisp +(use-package copilot + :straight (:host github :repo "copilot-emacs/copilot.el" :files ("*.el")) + :ensure t + :hook ((prog-mode) . copilot-mode) + :bind ( + ("TAB" . 'copilot-accept-completion) + ("C-" . 'copilot-accept-completion) + ) + ) +#+end_src + +*** COMMENT Ollama I feel so bad for this.. but its not awful.. #+begin_src emacs-lisp @@ -1533,7 +1550,9 @@ LSP sets it's prefix key to =s-l= by default, which uses the Super key which I u lsp-rust-analyzer-proc-macro-enable t lsp-rust-analyzer-binding-mode-hints t lsp-rust-analyzer-display-closure-return-type-hints t - lsp-rust-analyzer-server-format-inlay-hints t) + lsp-rust-analyzer-server-format-inlay-hints t + + lsp-enable-suggest-server-download nil) (setq lsp-glsl-executable '("glsl_analyzer")) (add-to-list 'lsp-language-id-configuration '("CMakeLists.txt" . "cmake")) @@ -1609,6 +1628,11 @@ hlsl-mode: #+end_src #+begin_src emacs-lisp +(require 'slang-ts-mode) +(add-hook 'slang-ts-mode-hook (lambda () (hs-minor-mode -1))) +#+end_src + +#+begin_src emacs-lisp :tangle "local-lisp/slang-ts-mode.el" (require 'treesit) (add-to-list @@ -1635,7 +1659,6 @@ hlsl-mode: (defcustom slang-ts-mode-indent-offset 4 "Number of spaces for each indentation step in `slang-ts-mode'." - :version "29.1" :type 'integer :safe 'integerp :group 'slang) @@ -1829,7 +1852,7 @@ delimiters < and >'s." '(((field_identifier) @font-lock-property-use-face)) )) -(define-derived-mode slang-ts-mode prog-mode "Slang" +(define-derived-mode slang-ts-mode c-ts-mode "Slang" "Major mode for editing Slang, powered by tree-sitter." :group 'slang :syntax-table slang-ts-mode--syntax-table diff --git a/local-lisp/ollama-complete.el b/local-lisp/ollama-complete.el new file mode 100644 index 0000000..8ae6821 --- /dev/null +++ b/local-lisp/ollama-complete.el @@ -0,0 +1,85 @@ +(defgroup ollama-complete nil "Ollama Code Completion." :group 'completion) + +(require 'plz) + +(defcustom ollama-complete-host "http://localhost:11434" + "URL of local ollama service." + :type 'url) + +(defcustom ollama-complete-model "qwen2.5-coder:3b-instruct-q4_K_M" + "Model to use for Fill-in-Middle completion.") + +(defvar ollama-complete--options + '(("temperature" . 0) ("top_p" . 0.5) ("num_predict" . 30))) + +(defvar ollama-complete--overlay nil) + +(defvar ollama-complete--overlay-buffer nil + "Buffer in which the overlay is placed.") + +(defun ollama-complete--fill-in-middle () + "Ask ollama to generate response for fill-in-middle prompt." + (interactive) + (let ((prompt + (concat + "<|fim_prefix|>" + (concat + (buffer-substring-no-properties (point-min) (point)) + (concat + "<|fim_suffix|>" + (concat + (buffer-substring-no-properties (point) (point-max)) + "<|fim_middle|>")))))) + (setq ollama-complete--overlay-buffer (current-buffer)) + (message "overlay-buffer: %s" ollama-complete--overlay-buffer) + (plz 'post + (concat ollama-complete-host "/api/generate") + :body (json-encode `(("model" . "qwen2.5-coder:3b-instruct-q4_K_M") + ("raw" . t) + ("stream" . :json-false) + ("options" . ,ollama-complete--options) + ("prompt" . ,prompt) + )) + :as #'json-read + :then (lambda (alist) + (message "Ollama: FIM Completion: %s" (alist-get 'response alist)) + (ollama-complete--make-overlay (alist-get 'response alist)))) + ) + ) + +(defun ollama-complete--make-overlay (string) + "make overlay showign STRING at POS, or move existing overlay there." + (interactive) + (if ollama-complete--overlay-buffer + (with-current-buffer ollama-complete--overlay-buffer + (message "make-overlay %d \"%s\" %s" (point) string ollama-complete--overlay-buffer) + (if ollama-complete--overlay + (move-overlay ollama-complete--overlay (point) (point) ollama-complete--overlay-buffer) + (setq ollama-complete--overlay (make-overlay (point) (point) ollama-complete--overlay-buffer)) + (overlay-put ollama-complete--overlay 'window (selected-window)) + (overlay-put ollama-complete--overlay + 'after-string (propertize string 'face 'font-lock-comment-face)) + (add-text-properties 0 1 '(cursor 1) string) + ollama-complete--overlay))) + ) + +(defun ollama-complete--hide-overlay () + "Hide temporary completion candidate overlay." + (interactive) + (when ollama-complete--overlay + (delete-overlay ollama-complete--overlay) + (setq ollama-complete--overlay nil) + (setq ollama-complete--overlay-buffer nil)) + ) + +(defun ollama-complete--insert-completion () + "Hide temporary completion candidate overlay." + (interactive) + (when ollama-complete--overlay + (let ((completion (overlay-get ollama-complete--overlay 'after-string))) + (set-text-properties 0 (length completion) nil completion) + (goto-char (overlay-start ollama-complete--overlay)) + (insert (substring-no-properties completion))) + (ollama-complete--hide-overlay))) + +(provide 'ollama-complete) diff --git a/local-lisp/slang-ts-mode.el b/local-lisp/slang-ts-mode.el new file mode 100644 index 0000000..cb867ec --- /dev/null +++ b/local-lisp/slang-ts-mode.el @@ -0,0 +1,243 @@ +(require 'treesit) + +(add-to-list + 'treesit-language-source-alist + '(slang "https://github.com/tree-sitter-grammars/tree-sitter-slang")) + +(with-eval-after-load 'lsp-mode + (progn + ;; tree-sitter + + ;; LSP + (add-to-list 'lsp-language-id-configuration '(".*\\.slang$" . "slang")) + (lsp-register-client (make-lsp-client + :new-connection (lsp-stdio-connection "/opt/shader-slang-bin/bin/slangd") + :activation-fn (lsp-activate-on "slang") + :server-id 'slang)) + )) + +(require 'c-ts-common) +(require 'c-ts-mode) + +(defgroup slang nil "Khronos Slang Major Mode." + :group 'languages) + +(defcustom slang-ts-mode-indent-offset 4 + "Number of spaces for each indentation step in `slang-ts-mode'." + :type 'integer + :safe 'integerp + :group 'slang) + +(declare-function treesit-parser-create "treesit.c") +(declare-function treesit-node-parent "treesit.c") +(declare-function treesit-node-start "treesit.c") +(declare-function treesit-node-end "treesit.c") +(declare-function treesit-node-child "treesit.c") +(declare-function treesit-node-child-by-field-name "treesit.c") +(declare-function treesit-node-type "treesit.c") +(declare-function treesit-node-prev-sibling "treesit.c") +(declare-function treesit-node-first-child-for-pos "treesit.c") +(declare-function treesit-node-next-sibling "treesit.c") +(declare-function treesit-parser-set-included-ranges "treesit.c") +(declare-function treesit-query-compile "treesit.c") + +;; taken from rust-ts-mode +(defvar slang-ts-mode--syntax-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?+ "." table) + (modify-syntax-entry ?- "." table) + (modify-syntax-entry ?= "." table) + (modify-syntax-entry ?% "." table) + (modify-syntax-entry ?& "." table) + (modify-syntax-entry ?| "." table) + (modify-syntax-entry ?^ "." table) + (modify-syntax-entry ?! "." table) + (modify-syntax-entry ?@ "." table) + (modify-syntax-entry ?~ "." table) + (modify-syntax-entry ?< "." table) + (modify-syntax-entry ?> "." table) + (modify-syntax-entry ?/ ". 124b" table) + (modify-syntax-entry ?* ". 23" table) + (modify-syntax-entry ?\n "> b" table) + (modify-syntax-entry ?\^m "> b" table) + table) + "Syntax table for `slang-ts-mode'.") + +(defvar slang-ts-mode--indent-rules + `((slang + ((parent-is "translation_unit") column-0 0) + ((node-is ")") parent-bol 0) + ((node-is "]") parent-bol 0) + ((node-is "}") (and parent parent-bol) 0) + ((and (parent-is "comment") c-ts-common-looking-at-star) + c-ts-common-comment-start-after-first-star -1) + ((parent-is "comment") prev-adaptive-prefix 0) + ((parent-is "parameter_list") parent-bol slang-ts-mode-indent-offset) + ((parent-is "binary_expression") parent-bol slang-ts-mode-indent-offset) + ((parent-is "compount_statement") parent-bol slang-ts-mode-indent-offset) + ((parent-is "field_declaration_list") parent-bol slang-ts-mode-indent-offset) + )) + "Tree-sitter indent rules for `slang-ts-mode'.") + +;; taken from rust-ts-mode +(defun slang-ts-mode--syntax-propertize (beg end) + "Apply syntax properties to special characters between BEG and END. + +Apply syntax properties to various special characters with +contextual meaning between BEG and END. + +The apostrophe \\=' should be treated as string when used for char literals. + +< and > are usually punctuation, e.g., as greater/less-than. But +when used for types, they should be considered pairs. + +This function checks for < and > in the changed RANGES and apply +appropriate text property to alter the syntax of template +delimiters < and >'s." + (goto-char beg) + (while (search-forward "'" end t) + (when (string-equal "char_literal" + (treesit-node-type + (treesit-node-at (match-beginning 0)))) + (put-text-property (match-beginning 0) (match-end 0) + 'syntax-table (string-to-syntax "\"")))) + (goto-char beg) + (while (re-search-forward (rx (or "<" ">")) end t) + (pcase (treesit-node-type + (treesit-node-parent + (treesit-node-at (match-beginning 0)))) + ("template_argument_list" + (put-text-property (match-beginning 0) + (match-end 0) + 'syntax-table + (pcase (char-before) + (?< '(4 . ?>)) + (?> '(5 . ?<)))))))) + +;; (treesit-query-validate 'slang "(bitfield_clause (identifier) @font-lock-builtin-face) (:match ,(rx bos (or ,@slang-ts-mode--locations) eos))") + +(defvar slang-ts-mode--locations + '("SV_Position" "COLOR" "POSITION" "SV_Target") + "Slang built-in location hints for font-locking.") + +(defvar slang-ts-mode--keywords + '("struct" "interface" "where" "return") + "Slang built-in location hints for font-locking.") + +(defvar slang-ts-mode--types + `(,@(mapcar (lambda (type) + (concat type "\\([1234]?\\|\\([1234]x[1234]\\)?\\)")) + '("bool" "int" "uint" "float" + "min16float" "min10float" "min16int" "min12int" "min16uint"))) + "Slang types for font-locking.") + +(defvar slang-ts-mode--operators + '("!" "!=" "%" "%=" "&" "&=" "&&" "*" "*=" "+" "+=" "," "-" "-=" + "->" "." "/" "/=" ":" ";" "<<" "<<=" "<" "<=" + "=" "==" "=>" ">" ">=" ">>" ">>=" "^" "^=" "|" "|=" "||") + "Slang operators for tree-sitter font-locking.") + +(defvar slang-ts-mode--font-lock-settings + (treesit-font-lock-rules + :language 'slang + :feature 'bracket + '((["(" ")" "[" "]" "{" "}"]) @font-lock-bracket-face) + + :language 'slang + :feature 'comment + '(((comment) @font-lock-comment-face)) + + :language 'slang + :feature 'builtin + '((bitfield_clause (identifier) @font-lock-builtin-face) + (semantics (identifier) @font-lock-builtin-face)) + + :language 'slang + :feature 'keyword + `([,@slang-ts-mode--keywords] @font-lock-keyword-face) + + :language 'slang + :feature 'type + `( + ((call_expression function: (identifier) @font-lock-type-face) + (:match ,(rx bos + (and (or "bool" "int" "uint" "float") + (or + (? (any "1" "2" "3" "4")) + (? (and (any "1" "2" "3" "4") "x" (any "1" "2" "3" "4"))))) + eos) @font-lock-type-face)) + ((call_expression function: (identifier) @font-lock-function-call-face)) + (type_identifier) @font-lock-type-face) + + :language 'slang + :feature 'definition + '( + (declaration declarator: (identifier) @font-lock-property-name-face) + (field_declaration declarator: (field_identifier) @font-lock-property-name-face) + (parameter_declaration declarator: (identifier) @font-lock-property-name-face) + (function_declarator declarator: (identifier) @font-lock-function-name-face) + (function_declarator declarator: (template_function name: (identifier) @font-lock-type-face)) + (hlsl_attribute (call_expression function: (identifier) @font-lock-builtin-face)) + ) + + :language 'slang + :feature 'function + '((call_expression function: (identifier) @font-lock-function-call-face) + (call_expression function: (_ field: (field_identifier) @font-lock-function-call-face)) + ) + + :language 'slang + :feature 'string + '(((string_content) @font-lock-string-face)) + + :language 'slang + :feature 'type + '(((type_identifier) @font-lock-type-face) + (function_definition type: (type_identifier) @font-lock-type-face) + (declaration type: (type_identifier) @font-lock-type-face) + (field_declaration type: (type_identifier) @font-lock-type-face) + (parameter_declaration type: (type_identifier) @font-lock-type-face) + (template_argument_list (type_descriptor type: (type_identifier) @font-lock-type-face)) + ) + + :language 'slang + :feature 'operator + `([,@slang-ts-mode--operators] @font-lock-operator-face) + + :language 'slang + :feature 'variable + '(((identifier) @font-lock-property-use-face)) + + :language 'slang + :feature 'number + '(((number_literal) @font-lock-number-face)) + + :language 'slang + :feature 'property + '(((field_identifier) @font-lock-property-use-face)) + )) + +(define-derived-mode slang-ts-mode c-ts-mode "Slang" + "Major mode for editing Slang, powered by tree-sitter." + :group 'slang + :syntax-table slang-ts-mode--syntax-table + + (when (treesit-ready-p 'slang) + (treesit-parser-create 'slang) + (setq-local treesit-font-lock-feature-list + '((comment definition) + (keyword string) + (assignment attribute builtin variable constant escape-sequence number definition property type) + (bracket delimiter error function operator property variable) + )) + (setq-local syntax-propertize-function #'slang-ts-mode--syntax-propertize + indent-tabs-mode nil + treesit-font-lock-settings slang-ts-mode--font-lock-settings + treesit-simple-indent-rules slang-ts-mode--indent-rules) + (treesit-major-mode-setup)) + ) + +(if (treesit-ready-p 'slang) + (add-to-list 'auto-mode-alist '("\\.slang\\'" . slang-ts-mode))) + +(provide 'slang-ts-mode)