setup odin mode
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -4,3 +4,8 @@ elpa/
|
||||
transient/
|
||||
tramp
|
||||
auto-save-list
|
||||
history
|
||||
projects
|
||||
eshell
|
||||
parinfer-rust
|
||||
.mc-lists.el
|
||||
17
custom.el
17
custom.el
@@ -5,11 +5,18 @@
|
||||
;; Your init file should contain only one such instance.
|
||||
;; If there is more than one, they won't work right.
|
||||
'(package-selected-packages
|
||||
'(aider browse-kill-ring cider company corfu exec-path-from-shell
|
||||
haskell-mode haskell-ts-mode helm marginalia
|
||||
markdown-ts-mode multiple-cursors orderless org-mode sly
|
||||
terraform-mode tree-sitter-langs vertico visual-fill-column
|
||||
yasnippet-snippets)))
|
||||
'(aider browse-kill-ring caddyfile-mode cape cider company corfu
|
||||
dockerfile-mode dumb-jump dumber-jump emacs-lldb
|
||||
exec-path-from-shell flycheck fsharp-mode haskell-mode
|
||||
haskell-ts-mode helm htmlize idris-mode marginalia
|
||||
markdown-ts-mode multiple-cursors orderless org-mode
|
||||
parinfer-rust-mode realgud-lldb rg sly terraform-mode
|
||||
tree-sitter-langs vertico visual-fill-column
|
||||
yasnippet-snippets zig-mode))
|
||||
'(safe-local-variable-directories '("/Users/grant/programming/project/edit/"))
|
||||
'(safe-local-variable-values
|
||||
'((Package . CL-USER) (Syntax . ANSI-Common-Lisp) (Base . 10)
|
||||
(flycheck-clang-includes . "SDL3-3.2.26/include"))))
|
||||
(custom-set-faces
|
||||
;; custom-set-faces was added by Custom.
|
||||
;; If you edit it by hand, you could mess it up, so be careful.
|
||||
|
||||
208
init.el
208
init.el
@@ -1,3 +1,5 @@
|
||||
;; -*- lexical-binding: t; -*-
|
||||
|
||||
(require 'package)
|
||||
(add-to-list 'package-archives
|
||||
'("melpa" . "https://melpa.org/packages/") t)
|
||||
@@ -6,6 +8,9 @@
|
||||
(require 'use-package-ensure)
|
||||
(require 'bind-key)
|
||||
|
||||
; If startup times are slow
|
||||
; (setq use-package-verbose t)
|
||||
|
||||
(use-package emacs)
|
||||
(setq tab-bar-show nil)
|
||||
(setq inhibit-startup-message t)
|
||||
@@ -27,12 +32,24 @@
|
||||
(setq reb-re-syntax 'string)
|
||||
(setq default-tab-width 4)
|
||||
(setq-default tab-width 4)
|
||||
(set-face-attribute 'default nil :height 160 :family "Monaco")
|
||||
(set-face-attribute 'default nil :height 160 :family "Berkeley Mono")
|
||||
(global-hl-line-mode 1)
|
||||
|
||||
(setq use-package-always-ensure t)
|
||||
(setq mac-command-modifier 'control)
|
||||
(setq is-mac (string= system-type "darwin"))
|
||||
|
||||
(setq-default cursor-type 'bar)
|
||||
|
||||
(defun hgh/disable-bar-cursor ()
|
||||
(blink-cursor-mode -1))
|
||||
|
||||
(defun hgh/enable-bar-cursor ()
|
||||
(blink-cursor-mode 1))
|
||||
|
||||
(add-hook 'activate-mark-hook 'hgh/disable-bar-cursor)
|
||||
(add-hook 'deactivate-mark-hook 'hgh/enable-bar-cursor)
|
||||
|
||||
(when is-mac
|
||||
(setq dired-use-ls-dired t
|
||||
insert-directory-program "gls"
|
||||
@@ -61,59 +78,93 @@
|
||||
|
||||
(defun hgh/project-ripgrep (regexp)
|
||||
(interactive (list (read-from-minibuffer "Search (regexp): " (thing-at-point 'symbol))))
|
||||
(ripgrep-regexp regexp (project-root (project-current))))
|
||||
(rg regexp "*" (project-root (project-current))))
|
||||
|
||||
(defun hgh/current-date-time ()
|
||||
(interactive)
|
||||
(insert (format-time-string "%Y-%m-%d %H:%M:%S")))
|
||||
|
||||
(add-hook 'compilation-filter-hook 'ansi-color-compilation-filter)
|
||||
|
||||
(defun hgh/next-error ()
|
||||
(interactive)
|
||||
(if (eglot-managed-p)
|
||||
(flymake-goto-next-error)
|
||||
(next-error)))
|
||||
|
||||
;; key bindings
|
||||
(keymap-global-set "M-o" #'other-window)
|
||||
(keymap-global-set "M-i" #'imenu)
|
||||
(keymap-global-set "C-M-." #'end-of-buffer)
|
||||
(keymap-global-set "C-M-," #'beginning-of-buffer)
|
||||
(keymap-global-set "C-." #'xref-find-definitions)
|
||||
(keymap-global-set "C-," #'xref-go-back)
|
||||
(keymap-global-set "<f5>" #'compile)
|
||||
(keymap-global-set "C-c r r" #'revert-buffer)
|
||||
(keymap-global-set "C-c C-c" #'comment-or-uncomment-region)
|
||||
(keymap-global-set "M-]" #'forward-paragraph)
|
||||
(keymap-global-set "M-[" #'backward-paragraph)
|
||||
(keymap-global-set "C-h h" #'eldoc)
|
||||
(keymap-global-set "C-]" #'flymake-goto-next-error)
|
||||
(keymap-global-set "C-]" #'hgh/next-error)
|
||||
(keymap-global-set "C-c e i" #'hgh/visit-init-file)
|
||||
(keymap-global-set "C-c c" #'compile)
|
||||
(keymap-global-set "C-x C-b" #'ibuffer)
|
||||
(keymap-global-set "M-0" #'delete-window)
|
||||
(keymap-global-set "M-1" #'delete-other-windows)
|
||||
(keymap-global-set "M-2" #'split-window-below)
|
||||
(keymap-global-set "M-3" #'split-window-right)
|
||||
|
||||
(require 'dired)
|
||||
(setq dired-dwim-target t)
|
||||
(keymap-set dired-mode-map "C-c C-c" #'wdired-change-to-wdired-mode)
|
||||
|
||||
(load-theme 'modus-vivendi-tinted t)
|
||||
(load-theme 'modus-vivendi t)
|
||||
|
||||
(use-package exec-path-from-shell
|
||||
:when is-mac
|
||||
:config
|
||||
(exec-path-from-shell-initialize))
|
||||
|
||||
(use-package man
|
||||
:when is-mac
|
||||
:custom
|
||||
(manual-program "gman"))
|
||||
|
||||
(use-package magit
|
||||
:defer t)
|
||||
|
||||
(use-package tree-sitter
|
||||
:mode (("\\.tsx\\'" . tsx-ts-mode)
|
||||
("\\.js\\'" . typescript-ts-mode)
|
||||
("\\.mjs\\'" . typescript-ts-mode)
|
||||
("\\.mts\\'" . typescript-ts-mode)
|
||||
("\\.cjs\\'" . typescript-ts-mode)
|
||||
("\\.ts\\'" . typescript-ts-mode)
|
||||
("\\.jsx\\'" . tsx-ts-mode)
|
||||
("\\.json\\'" . json-ts-mode))
|
||||
:mode ((" \\.tsx\\'" . tsx-ts-mode)
|
||||
(" \\.js\\'" . typescript-ts-mode)
|
||||
(" \\.mjs\\'" . typescript-ts-mode)
|
||||
(" \\.mts\\'" . typescript-ts-mode)
|
||||
(" \\.cjs\\'" . typescript-ts-mode)
|
||||
(" \\.ts\\'" . typescript-ts-mode)
|
||||
(" \\.jsx\\'" . tsx-ts-mode)
|
||||
(" \\.json\\'" . json-ts-mode))
|
||||
:custom
|
||||
(treesit-extra-load-path '("~/repos/tree-sitter-module/dist")))
|
||||
|
||||
(use-package tree-sitter-langs)
|
||||
(use-package tree-sitter-langs
|
||||
:defer t)
|
||||
|
||||
(use-package haskell-mode)
|
||||
(use-package haskell-mode
|
||||
:defer t)
|
||||
|
||||
(use-package company)
|
||||
|
||||
(defun enable-parinfer ()
|
||||
(let ((buf (or (buffer-file-name) (buffer-name) "")))
|
||||
(when (and
|
||||
(not (s-contains? "sbcl" buf))
|
||||
(not (s-contains? "ocicl" buf))
|
||||
(not (string-prefix-p "*sly" buf)))
|
||||
(parinfer-rust-mode 1)
|
||||
(electric-quote-mode 1))))
|
||||
|
||||
(use-package parinfer-rust-mode
|
||||
:hook ((lisp-mode emacs-lisp-mode) . enable-parinfer)
|
||||
:config
|
||||
(setq parinfer-rust-disable-troublesome-modes t))
|
||||
|
||||
(use-package sly
|
||||
:defer t
|
||||
:custom
|
||||
(inferior-lisp-program "/opt/homebrew/bin/sbcl"))
|
||||
|
||||
@@ -147,13 +198,13 @@
|
||||
:config
|
||||
(global-corfu-mode 1))
|
||||
|
||||
(use-package cape
|
||||
:init
|
||||
(add-to-list 'completion-at-point-functions #'cape-dabbrev))
|
||||
|
||||
(use-package browse-kill-ring
|
||||
:bind (("C-c y" . browse-kill-ring)))
|
||||
|
||||
(defun hgh/org-mode-setup ()
|
||||
(org-indent-mode)
|
||||
(visual-line-mode 1))
|
||||
|
||||
(defun hgh/org-mode-visual-fill ()
|
||||
(setq visual-fill-column-width 120
|
||||
visual-fill-column-center-text t)
|
||||
@@ -173,7 +224,8 @@
|
||||
(java-ts-mode . eglot-ensure)
|
||||
(svelte-mode . eglot-ensure)
|
||||
(haskell-mode . eglot-ensure)
|
||||
(terraform-mode . eglot-ensure))
|
||||
(terraform-mode . eglot-ensure)
|
||||
(odin-mode . eglot-ensure))
|
||||
:bind
|
||||
(:map eglot-mode-map
|
||||
("C-c r" . eglot-rename)
|
||||
@@ -188,15 +240,19 @@
|
||||
(cl-remove-if (lambda (c) (equal (car c) 'rust-mode))
|
||||
eglot-server-programs))
|
||||
|
||||
(setf eglot-server-programs (cons (list '(rust-ts-mode rust-mode) "rust-analyzer" :initializationOptions '(:checkOnSave (:command "clippy")))
|
||||
eglot-server-programs))
|
||||
|
||||
(setf eglot-server-programs (cons '(svelte-mode "svelteserver" "--stdio")
|
||||
eglot-server-programs))
|
||||
|
||||
(setf eglot-server-programs (cons '(haskell-mode "haskell-language-server-wrapper" "--lsp")
|
||||
(setf eglot-server-programs
|
||||
(append (list
|
||||
(list '(rust-ts-mode rust-mode) "rust-analyzer" :initializationOptions '(:checkOnSave (:command "clippy")))
|
||||
'(svelte-mode "svelteserver" "--stdio")
|
||||
'(haskell-mode "haskell-language-server-wrapper" "--lsp"))
|
||||
eglot-server-programs)))
|
||||
|
||||
(setenv "DOTNET_ROOT" "~/.local/share/mise/installs/dotnet/9")
|
||||
(push '("\\.csproj$" . xml-mode) auto-mode-alist)
|
||||
(push '("\\.vs$" . c-mode) auto-mode-alist)
|
||||
(push '("\\.fs$" . c-mode) auto-mode-alist)
|
||||
(push '("\\.sbclrc" . lisp-mode) auto-mode-alist)
|
||||
|
||||
;; paredit
|
||||
|
||||
; (autoload 'enable-paredit-mode "paredit" "Turn on pseudo-structural editing of Lisp code." t)
|
||||
@@ -209,18 +265,35 @@
|
||||
(define-key paredit-mode-map (kbd "M-:") #'paredit-backward-barf-sexp)
|
||||
(enable-paredit-mode))
|
||||
|
||||
(setq lisp-mode-hooks '((emacs-lisp-mode-hook emacs-lisp-mode)
|
||||
(defvar lisp-mode-hooks nil)
|
||||
(setf lisp-mode-hooks '((emacs-lisp-mode-hook emacs-lisp-mode)
|
||||
(clojure-mode-hook clojure-mode)
|
||||
(lisp-mode-hook lisp-mode)
|
||||
(sly-mode-hook sly-mode)))
|
||||
|
||||
(add-hook 'lisp-mode-hook
|
||||
(lambda ()
|
||||
(set (make-local-variable 'lisp-indent-function)
|
||||
'common-lisp-indent-function)
|
||||
(setup-paredit)))
|
||||
(defun hgh/rg (search)
|
||||
(interactive "sSearch: ")
|
||||
(compilation-start
|
||||
(concat "rg --no-heading '" search "'")
|
||||
'compilation-mode
|
||||
(lambda (s)
|
||||
(concat
|
||||
"*"
|
||||
(file-name-nondirectory (directory-file-name default-directory))
|
||||
" rg*"))))
|
||||
|
||||
(use-package multiple-cursors
|
||||
:init
|
||||
(add-hook 'multiple-cursors-mode-enabled-hook
|
||||
(lambda ()
|
||||
(remove-hook 'activate-mark-hook 'hgh/disable-bar-cursor)
|
||||
(remove-hook 'deactivate-mark-hook 'hgh/disable-bar-cursor)
|
||||
(blink-cursor-mode 1)))
|
||||
(add-hook 'multiple-cursors-mode-disabled-hook
|
||||
(lambda ()
|
||||
(add-hook 'activate-mark-hook 'hgh/disable-bar-cursor)
|
||||
(add-hook 'deactivate-mark-hook 'hgh/disable-bar-cursor)
|
||||
(blink-cursor-mode 1)))
|
||||
:config
|
||||
(global-set-key (kbd "C->") 'mc/mark-next-like-this)
|
||||
(global-set-key (kbd "C-<") 'mc/mark-previous-like-this))
|
||||
@@ -237,14 +310,6 @@
|
||||
(use-package markdown-mode
|
||||
:ensure t)
|
||||
|
||||
(use-package aider
|
||||
:custom
|
||||
(aider-args '("--model" "o4-mini" "--no-auto-accept-architect"))
|
||||
:bind
|
||||
("C-c a" . #'aider-transient-menu)
|
||||
:config
|
||||
(setenv "OPENAI_API_KEY" "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"))
|
||||
|
||||
;; Run Prettier only in certain major-modes before saving:
|
||||
(defvar hgh/prettier-modes
|
||||
'(tsx-ts-mode typescript-ts-mode typescript-ts-base-mode json-ts-mode javascript-mode js2-mode typescript-mode web-mode)
|
||||
@@ -264,8 +329,59 @@
|
||||
|
||||
(use-package terraform-mode)
|
||||
|
||||
(use-package cider)
|
||||
(use-package cider
|
||||
:defer t)
|
||||
|
||||
(use-package org
|
||||
:defer t
|
||||
:custom
|
||||
(org-todo-keywords '((sequence "TODO" "INPROGRESS" "DONE"))))
|
||||
(org-todo-keywords '((sequence "TODO" "INPROGRESS" "DONE")))
|
||||
(org-support-shift-select t)
|
||||
(org-html-validation-link nil)
|
||||
(org-html-head-include-default-style nil)
|
||||
(org-html-head-include-scripts nil)
|
||||
(org-html-head "<link rel=\"stylesheet\" href=\"https://cdn.simplecss.org/simple.min.css\" />")
|
||||
|
||||
:config
|
||||
(org-indent-mode)
|
||||
(require 'ox-publish)
|
||||
|
||||
(org-babel-do-load-languages
|
||||
'org-babel-load-languages
|
||||
'((shell . t)))
|
||||
|
||||
(setq org-publish-use-timestamps-flag nil)
|
||||
|
||||
(setq org-publish-project-alist
|
||||
(list
|
||||
(list "writings"
|
||||
:base-directory "~/Documents/writings/content"
|
||||
:publishing-directory "~/Documents/writings/public"
|
||||
:exclude "~/Documents/writings/notes"
|
||||
:recursive t
|
||||
:time-stamp-file nil
|
||||
:section-numbers nil
|
||||
:with-creator t
|
||||
:with-author nil))))
|
||||
|
||||
(use-package dumber-jump
|
||||
:init
|
||||
(add-hook 'xref-backend-functions #'dumber-jump-xref-activate))
|
||||
|
||||
(use-package flycheck)
|
||||
; :init (global-flycheck-mode)
|
||||
|
||||
|
||||
(use-package idris-mode)
|
||||
|
||||
(use-package htmlize)
|
||||
|
||||
(use-package zig-mode)
|
||||
|
||||
(use-package fsharp-mode)
|
||||
|
||||
(use-package caddyfile-mode)
|
||||
|
||||
(use-package dockerfile-mode)
|
||||
|
||||
(load-file (concat (file-name-parent-directory user-init-file) "odin-mode.el"))
|
||||
|
||||
310
odin-mode.el
Normal file
310
odin-mode.el
Normal file
@@ -0,0 +1,310 @@
|
||||
;;; odin-mode.el --- A minor mode for odin
|
||||
|
||||
;; Author: Ethan Morgan
|
||||
;; Keywords: odin, language, languages, mode
|
||||
;; Package-Requires: ((emacs "24.1"))
|
||||
;; Homepage: https://github.com/glassofethanol/odin-mode
|
||||
|
||||
;; This file is NOT part of GNU Emacs.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'rx)
|
||||
(require 'js)
|
||||
|
||||
(defgroup odin nil
|
||||
"Odin mode"
|
||||
:group 'languages)
|
||||
|
||||
;; `compilation-mode' configuration
|
||||
|
||||
(eval-after-load 'compile
|
||||
'(add-to-list 'compilation-error-regexp-alist '("^\\(.*?\\)(\\([0-9]+\\):\\([0-9]+\\).*" 1 2 3)))
|
||||
|
||||
(defconst odin-mode-syntax-table
|
||||
(let ((table (make-syntax-table)))
|
||||
(modify-syntax-entry ?\" "\"" table)
|
||||
(modify-syntax-entry ?\\ "\\" table)
|
||||
|
||||
;; additional symbols
|
||||
(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 ?< "." table)
|
||||
(modify-syntax-entry ?> "." table)
|
||||
(modify-syntax-entry ?? "." table)
|
||||
|
||||
;; Need this for #directive regexes to work correctly
|
||||
(modify-syntax-entry ?# "_" table)
|
||||
|
||||
;; Modify some syntax entries to allow nested block comments
|
||||
(modify-syntax-entry ?/ ". 124b" table)
|
||||
(modify-syntax-entry ?* ". 23n" table)
|
||||
(modify-syntax-entry ?\n "> b" table)
|
||||
(modify-syntax-entry ?\^m "> b" table)
|
||||
|
||||
table))
|
||||
|
||||
(defconst odin-builtins
|
||||
'("len" "cap"
|
||||
"typeid_of" "type_info_of"
|
||||
"swizzle" "complex" "real" "imag" "quaternion" "conj"
|
||||
"jmag" "kmag"
|
||||
"min" "max" "abs" "clamp"
|
||||
"expand_to_tuple"
|
||||
|
||||
"init_global_temporary_allocator"
|
||||
"copy" "pop" "unordered_remove" "ordered_remove" "clear" "reserve"
|
||||
"resize" "new" "new_clone" "free" "free_all" "delete" "make"
|
||||
"clear_map" "reserve_map" "delete_key" "append_elem" "append_elems"
|
||||
"append" "append_string" "clear_dynamic_array" "reserve_dynamic_array"
|
||||
"resize_dynamic_array" "incl_elem" "incl_elems" "incl_bit_set"
|
||||
"excl_elem" "excl_elems" "excl_bit_set" "incl" "excl" "card"
|
||||
"assert" "panic" "unimplemented" "unreachable"))
|
||||
|
||||
(defconst odin-keywords
|
||||
'("import" "foreign" "package"
|
||||
"where" "when" "if" "else" "for" "switch" "in" "notin" "do" "case"
|
||||
"break" "continue" "fallthrough" "defer" "return" "proc"
|
||||
"struct" "union" "enum" "bit_field" "bit_set" "map" "dynamic"
|
||||
"auto_cast" "cast" "transmute" "distinct" "opaque"
|
||||
"using" "inline" "no_inline"
|
||||
"size_of" "align_of" "offset_of" "type_of"
|
||||
|
||||
"context"
|
||||
;; "_"
|
||||
|
||||
;; Reserved
|
||||
"macro" "const"))
|
||||
|
||||
(defconst odin-constants
|
||||
'("nil" "true" "false"
|
||||
"ODIN_OS" "ODIN_ARCH" "ODIN_ENDIAN" "ODIN_VENDOR"
|
||||
"ODIN_VERSION" "ODIN_ROOT" "ODIN_DEBUG"))
|
||||
|
||||
(defconst odin-typenames
|
||||
'("bool" "b8" "b16" "b32" "b64"
|
||||
|
||||
"int" "i8" "i16" "i32" "i64"
|
||||
"i16le" "i32le" "i64le"
|
||||
"i16be" "i32be" "i64be"
|
||||
"i128" "u128"
|
||||
"i128le" "u128le"
|
||||
"i128be" "u128be"
|
||||
|
||||
"uint" "u8" "u16" "u32" "u64"
|
||||
"u16le" "u32le" "u64le"
|
||||
"u16be" "u32be" "u64be"
|
||||
|
||||
"f32" "f64"
|
||||
"complex64" "complex128"
|
||||
|
||||
"quaternion128" "quaternion256"
|
||||
|
||||
"rune"
|
||||
"string" "cstring"
|
||||
|
||||
"uintptr" "rawptr"
|
||||
"typeid" "any"
|
||||
"byte"))
|
||||
|
||||
(defconst odin-attributes
|
||||
'("builtin"
|
||||
"export"
|
||||
"static"
|
||||
"deferred_in" "deferred_none" "deferred_out"
|
||||
"require_results"
|
||||
"default_calling_convention" "link_name" "link_prefix"
|
||||
"deprecated" "private" "thread_local"))
|
||||
|
||||
|
||||
(defconst odin-proc-directives
|
||||
'("#force_inline"
|
||||
"#force_no_inline"
|
||||
"#type")
|
||||
"Directives that can appear before a proc declaration")
|
||||
|
||||
(defconst odin-directives
|
||||
(append '("#align" "#packed"
|
||||
"#any_int"
|
||||
"#raw_union"
|
||||
"#no_nil"
|
||||
"#complete"
|
||||
"#no_alias"
|
||||
"#c_vararg"
|
||||
"#assert"
|
||||
"#file" "#line" "#location" "#procedure" "#caller_location"
|
||||
"#load"
|
||||
"#defined"
|
||||
"#bounds_check" "#no_bounds_check"
|
||||
"#partial") odin-proc-directives))
|
||||
|
||||
(defun odin-wrap-word-rx (s)
|
||||
(concat "\\<" s "\\>"))
|
||||
|
||||
(defun odin-wrap-keyword-rx (s)
|
||||
(concat "\\(?:\\S.\\_<\\|\\`\\)" s "\\_>"))
|
||||
|
||||
(defun odin-wrap-directive-rx (s)
|
||||
(concat "\\_<" s "\\>"))
|
||||
|
||||
(defun odin-wrap-attribute-rx (s)
|
||||
(concat "[[:space:]\n]*@[[:space:]\n]*(?[[:space:]\n]*" s "\\>"))
|
||||
|
||||
(defun odin-keywords-rx (keywords)
|
||||
"build keyword regexp"
|
||||
(odin-wrap-keyword-rx (regexp-opt keywords t)))
|
||||
|
||||
(defun odin-directives-rx (directives)
|
||||
(odin-wrap-directive-rx (regexp-opt directives t)))
|
||||
|
||||
(defun odin-attributes-rx (attributes)
|
||||
(odin-wrap-attribute-rx (regexp-opt attributes t)))
|
||||
|
||||
(defconst odin-identifier-rx "[[:word:][:multibyte:]_]+")
|
||||
(defconst odin-hat-type-rx (rx (group (and "^" (1+ (any word "." "_"))))))
|
||||
(defconst odin-dollar-type-rx (rx (group "$" (or (1+ (any word "_")) (opt "$")))))
|
||||
(defconst odin-number-rx
|
||||
(rx (and
|
||||
symbol-start
|
||||
(or (and (+ digit) (opt (and (any "eE") (opt (any "-+")) (+ digit))))
|
||||
(and "0" (any "xX") (+ hex-digit)))
|
||||
(opt (and (any "_" "A-Z" "a-z") (* (any "_" "A-Z" "a-z" "0-9"))))
|
||||
symbol-end)))
|
||||
(defconst odin-proc-rx (concat "\\(\\_<" odin-identifier-rx "\\_>\\)\\s *::\\s *\\(" (odin-directives-rx odin-proc-directives) "\\)?\\s *\\_<proc\\_>"))
|
||||
|
||||
(defconst odin-type-rx (concat "\\_<\\(" odin-identifier-rx "\\)\\s *::\\s *\\(?:struct\\|enum\\|union\\|distinct\\)\\s *\\_>"))
|
||||
|
||||
|
||||
(defconst odin-font-lock-defaults
|
||||
`(
|
||||
;; Types
|
||||
(,odin-hat-type-rx 1 font-lock-type-face)
|
||||
(,odin-dollar-type-rx 1 font-lock-type-face)
|
||||
(,(odin-keywords-rx odin-typenames) 1 font-lock-type-face)
|
||||
(,odin-type-rx 1 font-lock-type-face)
|
||||
|
||||
;; Hash directives
|
||||
(,(odin-directives-rx odin-directives) 1 font-lock-preprocessor-face)
|
||||
|
||||
;; At directives
|
||||
(,(odin-attributes-rx odin-attributes) 1 font-lock-preprocessor-face)
|
||||
|
||||
;; Keywords
|
||||
(,(odin-keywords-rx odin-keywords) 1 font-lock-keyword-face)
|
||||
|
||||
;; single quote characters
|
||||
("'\\(\\\\.\\|[^']\\)'" . font-lock-constant-face)
|
||||
|
||||
;; Variables
|
||||
(,(odin-keywords-rx odin-builtins) 1 font-lock-builtin-face)
|
||||
|
||||
;; Constants
|
||||
(,(odin-keywords-rx odin-constants) 1 font-lock-constant-face)
|
||||
|
||||
;; Strings
|
||||
;; ("\\\".*\\\"" . font-lock-string-face)
|
||||
|
||||
;; Numbers
|
||||
(,(odin-wrap-word-rx odin-number-rx) . font-lock-constant-face)
|
||||
|
||||
;; Procedures
|
||||
(,odin-proc-rx 1 font-lock-function-name-face)
|
||||
|
||||
("---" . font-lock-constant-face)
|
||||
("\\.\\.<" . font-lock-constant-face)
|
||||
("\\.\\." . font-lock-constant-face)
|
||||
))
|
||||
|
||||
;; add setq-local for older emacs versions
|
||||
(unless (fboundp 'setq-local)
|
||||
(defmacro setq-local (var val)
|
||||
`(set (make-local-variable ',var) ,val)))
|
||||
|
||||
(defconst odin--defun-rx "\(.*\).*\{")
|
||||
|
||||
(defmacro odin-paren-level ()
|
||||
`(car (syntax-ppss)))
|
||||
|
||||
(defun odin-line-is-defun ()
|
||||
"return t if current line begins a procedure"
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(beginning-of-line)
|
||||
(let (found)
|
||||
(while (and (not (eolp)) (not found))
|
||||
(if (looking-at odin--defun-rx)
|
||||
(setq found t)
|
||||
(forward-char 1)))
|
||||
found)))
|
||||
|
||||
(defun odin-beginning-of-defun (&optional count)
|
||||
"Go to line on which current function starts."
|
||||
(interactive)
|
||||
(let ((orig-level (odin-paren-level)))
|
||||
(while (and
|
||||
(not (odin-line-is-defun))
|
||||
(not (bobp))
|
||||
(> orig-level 0))
|
||||
(setq orig-level (odin-paren-level))
|
||||
(while (>= (odin-paren-level) orig-level)
|
||||
(skip-chars-backward "^{")
|
||||
(backward-char))))
|
||||
(if (odin-line-is-defun)
|
||||
(beginning-of-line)))
|
||||
|
||||
(defun odin-end-of-defun ()
|
||||
"Go to line on which current function ends."
|
||||
(interactive)
|
||||
(let ((orig-level (odin-paren-level)))
|
||||
(when (> orig-level 0)
|
||||
(odin-beginning-of-defun)
|
||||
(end-of-line)
|
||||
(setq orig-level (odin-paren-level))
|
||||
(skip-chars-forward "^}")
|
||||
(while (>= (odin-paren-level) orig-level)
|
||||
(skip-chars-forward "^}")
|
||||
(forward-char)))))
|
||||
|
||||
(defalias 'odin-parent-mode
|
||||
(if (fboundp 'prog-mode) 'prog-mode 'fundamental-mode))
|
||||
|
||||
;;;###autoload
|
||||
(define-derived-mode odin-mode odin-parent-mode "Odin"
|
||||
:syntax-table odin-mode-syntax-table
|
||||
:group 'odin
|
||||
(setq bidi-paragraph-direction 'left-to-right)
|
||||
(setq-local require-final-newline mode-require-final-newline)
|
||||
(setq-local parse-sexp-ignore-comments t)
|
||||
(setq-local comment-start-skip "\\(//+\\|/\\*+\\)\\s *")
|
||||
(setq-local comment-start "//")
|
||||
(setq-local comment-end "")
|
||||
(setq-local indent-line-function 'js-indent-line)
|
||||
(setq-local font-lock-defaults '(odin-font-lock-defaults))
|
||||
(setq-local beginning-of-defun-function 'odin-beginning-of-defun)
|
||||
(setq-local end-of-defun-function 'odin-end-of-defun)
|
||||
(setq-local electric-indent-chars
|
||||
(append "{}():;," electric-indent-chars))
|
||||
(setq imenu-generic-expression
|
||||
`(("type" ,(concat "^" odin-type-rx) 1)
|
||||
("proc" ,(concat "^" odin-proc-rx) 1)))
|
||||
|
||||
(font-lock-ensure))
|
||||
|
||||
;;;###autoload
|
||||
(add-to-list 'auto-mode-alist '("\\.odin\\'" . odin-mode))
|
||||
|
||||
(provide 'odin-mode)
|
||||
|
||||
|
||||
;;; odin-mode.el ends here
|
||||
Reference in New Issue
Block a user