From 033155a1fb9931e1d226aacc3b0021c4aef58b28 Mon Sep 17 00:00:00 2001 From: Wojciech Kozlowski Date: Sun, 15 Dec 2019 16:06:26 +0100 Subject: [PATCH] Add P4, Protobuf, and Kerboscript modes --- external/kos-mode.el | 127 +++++++++++++++++++++++ external/p4_16-mode.el | 222 +++++++++++++++++++++++++++++++++++++++++ init.el | 5 +- modules/languages.el | 26 +++++ 4 files changed, 377 insertions(+), 3 deletions(-) create mode 100644 external/kos-mode.el create mode 100644 external/p4_16-mode.el diff --git a/external/kos-mode.el b/external/kos-mode.el new file mode 100644 index 0000000..6b3b6fe --- /dev/null +++ b/external/kos-mode.el @@ -0,0 +1,127 @@ +;;; kos-mode.el --- Summary +;; Copyright (C) 2015 Fabian Kantereit +;; Author: Fabian Kantereit +;; Keywords: kOS, KerboScript, KSP, Kerbal SpaceProgram +;;; Commentary: +;; +;; +;;; Code: + +;;;;;;;;;;;;;;; +;; Mode hook ;; +;;;;;;;;;;;;;;; +(defvar kos-mode-hook nil) + +;;;;;;;;;;;;;; +;; Mode map ;; +;;;;;;;;;;;;;; +(defvar kos-mode-map + (let ((map (make-keymap))) + map) + "Keymap for kOS major mode.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; autoload mode for ks files ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;###autoload +(add-to-list 'auto-mode-alist '("\\.ks\\'" . kos-mode)) + +;;;;;;;;;;;;;;;;;;;;; +;; Language Syntax ;; +;;;;;;;;;;;;;;;;;;;;; +(defconst kos-font-lock-keywords-1 + (list + ;; SHIP, STAGE, TIME, ENCOUNTER, CONFIG and TARGET + '("\\<\\(\\(SHIP\\|STAGE\\|TARGET\\|TIME\\|ENCOUNTER\\|CONFIG\\):\\(\\w*:?\\)*\\)\\>" . font-lock-keyword-face) + ;; ALT and ETA + '("\\<\\(ALT:\\(APOAPSIS\\|PERIAPSIS\\|RADAR\\)\\|ETA:\\(APOAPSIS\\|PERIAPSIS\\|TRANSITION\\)\\)\\>" . font-lock-keyword-face) + ;; GENERAL + `(,(regexp-opt '("UP" "PROGRAGE" "RETROGRADE" "FACING" "MAXTHRUST" "VELOCITY" "GEOPOSITION" "THROTTLE" "STEERING" "STAGE" "SHIP" "HEADING" "LATITUDE" "LONGITUDE" "NORTH" "BODY" "ANGULARMOMENTUM" "ANGULARVEL" "ANGULARVELOCITY" "COMMRANGE" "MASS" "VERTICALSPEED" "SURFACESPEED" "AIRSPEED" "VESSELNAME" "ALTITUDE" "APOAPSIS" "PERIAPSIS" "SENSORS" "SRFPROGRADE" "SRFRETROGRADE" "OBT" "STATUS" "WHEELTHROTTLE" "WHEELSTEERING" "SAS" "RCS" "GEAR" "LEGS" "CHUTES" "LIGHTS" "PANELS" "BRAKES" "ABORT" "VERSION" "VERSION:MAJOR" "VERSION:MINOR" "SESSIONTIME" "TIME" "MAPVIEW" "WARP" "WARPMODE") 'words) . font-lock-keyword-face) + ;; Action Groups + '("\\" . font-lock-keyword-face) + ;; Builtin Language Features + `(,(regexp-opt '("SET" "TO" "IF" "ELSE" "UNTIL" "LOCK" "UNLOCK" "PRINT" "AT" "TOGGLE" + "WAIT" "WHEN" "THEN" "OFF" "CLEARSCREEN" "ADD" "REMOVE" "LOG" + "BREAK" "PRESERVE" "DECLARE" "PARAMETER" "SWITCH" "COPY" "FROM" "RENAME" + "VOLUME" "FILE" "DELETE" "EDIT" "RUN" "COMPILE" "LIST" "REBOOT" "SHUTDOWN" + "FOR" "UNSET" "BATCH" "DEPLOY" "IN" "ALL") 'words) . font-lock-builtin-face) + '("\\('\\w*'\\)" . font-lock-variable-name-face)) + "Primary highlighting expressions for kOS mode.") + +(defconst kos-font-lock-keywords-2 + (append kos-font-lock-keywords-1 + (list + '("\\<\\(ON\\|OFF\\|TRUE\\|FALSE\\)\\>" . font-lock-constant-face) ;; ON / OFF keywords + '("\"[^\"]+\"" . font-lock-string-face) ;; string literals + '("\\b[-]?[0-9]+\\b" . font-lock-preprocessor-face) ;; integer literals + '("\\b[-+]?[0-9]+\.[0-9]*\([eE][-+]?[0-9]+\)?\\b" . font-lock-preprocessor-face) ;; floating point literals + ) + ) + "Additional Keywords to highlight in kOS (KerboScript) mode.") + +(defvar kos-font-lock-keywords kos-font-lock-keywords-2 + "Default highlighting expressions for kOS (KerboScript) mode.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Syntax table for comments ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +(defvar kos-mode-syntax-table + (let ((st (make-syntax-table))) + (modify-syntax-entry ?_ "w" st) + (modify-syntax-entry ?/ ". 124b" st) + (modify-syntax-entry ?\n "> b" st) + st) + "Syntax table for kos-mode.") + +;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Indentation function ;; +;;;;;;;;;;;;;;;;;;;;;;;;;; +(defvar kos-indent-offset 4 + "Indentation offset for `kos-mode'.") + +(defun kos-indent-line () + "Indent current line for any balanced-paren-mode'." + (interactive) + (let ((indent-col 0) + (indentation-increasers "[{(]") + (indentation-decreasers "[})]")) + (save-excursion + (beginning-of-line) + (condition-case nil + (while t + (backward-up-list 1) + (when (looking-at indentation-increasers) + (setq indent-col (+ indent-col kos-indent-offset)))) + (error nil))) + (save-excursion + (back-to-indentation) + (when (and (looking-at indentation-decreasers) + (>= indent-col kos-indent-offset)) + (setq indent-col (- indent-col kos-indent-offset)))) + (indent-line-to indent-col))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; Major mode definition ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;; +(define-derived-mode kos-mode prog-mode "KerboScript" + "Major mode for editing KerboScript Files" + :syntax-table kos-mode-syntax-table + ;; Keymap + (use-local-map kos-mode-map) + ;; set syntax highlighting + (set (make-local-variable 'font-lock-defaults) '(kos-font-lock-keywords nil t)) + ;; this should be case insensitive + (set (make-local-variable 'font-lock-keywords-case-fold-search) t) + ;; indentation + (set (make-local-variable 'indent-line-function) 'kos-indent-line) + + ;; support for comment shortcuts + (setq comment-start "// ") + (setq comment-end "") + ;; hook for loading additional modules + (run-hooks 'kos-mode-hook) + ) + +(provide 'kos-mode) + +;;; kos-mode.el ends here diff --git a/external/p4_16-mode.el b/external/p4_16-mode.el new file mode 100644 index 0000000..7625d90 --- /dev/null +++ b/external/p4_16-mode.el @@ -0,0 +1,222 @@ +;;; p4_16-mode.el --- Support for the P4_16 programming language + +;; Copyright (C) 2016- Barefoot Networks +;; Author: Vladimir Gurevich +;; Maintainer: Vladimir Gurevich +;; Created: 15 April 2017 +;; Version: 0.2 +;; Keywords: languages p4_16 +;; Homepage: http://p4.org + +;; This file is not part of GNU Emacs. + +;; This file is free software… + +;; This mode has preliminary support for P4_16. It covers the core language, +;; but it is not clear yet, how we can highlight the indentifiers, defined +;; for a particular architecture. Core library definitions are included + +;; Placeholder for user customization code +(defvar p4_16-mode-hook nil) + +;; Define the keymap (for now it is pretty much default) +(defvar p4_16-mode-map + (let ((map (make-keymap))) + (define-key map "\C-j" 'newline-and-indent) + map) + "Keymap for P4_16 major mode") + +;; Syntactic HighLighting + +;; Main keywors (declarations and operators) +(setq p4_16-keywords + '("action" "apply" + "control" + "default" + "else" "enum" "extern" "exit" + "header" "header_union" + "if" + "match_kind" + "package" "parser" + "return" + "select" "state" "struct" "switch" + "table" "transition" "tuple" "typedef" + "verify" + )) + +(setq p4_16-annotations + '("@name" "@metadata" "@alias" + )) + +(setq p4_16-attributes + '("const" "in" "inout" "out" + ;; Tables + "key" "actions" "default_action" "entries" "implementation" + "counters" "meters" + )) + +(setq p4_16-variables + '("packet_in" "packet_out" + )) + +(setq p4_16-operations + '("&&&" ".." "++" "?" ":")) + +(setq p4_16-constants + '( + ;;; Don't care + "_" + ;;; bool + "false" "true" + ;;; error + "NoError" "PacketTooShort" "NoMatch" "StackOutOfBounds" + "OverwritingHeader" "HeaderTooShort" "ParserTiimeout" + ;;; match_kind + "exact" "ternary" "lpm" "range" + ;;; We can add constants for supported architectures here + )) + +(setq p4_16-types + '("bit" "bool" "int" "varbit" "void" "error" + )) + +(setq p4_16-primitives + '( + ;;; Header methods + "isValid" "setValid" "setInvalid" + ;;; Table Methods + "hit" "action_run" + ;;; packet_in methods + "extract" "lookahead" "advance" "length" + ;;; packet_out methods + "emit" + ;;; Known parser states + "accept" "reject" + ;;; misc + "NoAction" + )) + +(setq p4_16-cpp + '("#include" + "#define" "#undef" + "#if" "#ifdef" "#ifndef" + "#elif" "#else" + "#endif" + "defined" + "#line" "#file")) + +(setq p4_16-cppwarn + '("#error" "#warning")) + +;; Optimize the strings +(setq p4_16-keywords-regexp (regexp-opt p4_16-keywords 'words)) +(setq p4_16-annotations-regexp (regexp-opt p4_16-annotations 1)) +(setq p4_16-attributes-regexp (regexp-opt p4_16-attributes 'words)) +(setq p4_16-variables-regexp (regexp-opt p4_16-variables 'words)) +(setq p4_16-operations-regexp (regexp-opt p4_16-operations 'words)) +(setq p4_16-constants-regexp (regexp-opt p4_16-constants 'words)) +(setq p4_16-types-regexp (regexp-opt p4_16-types 'words)) +(setq p4_16-primitives-regexp (regexp-opt p4_16-primitives 'words)) +(setq p4_16-cpp-regexp (regexp-opt p4_16-cpp 1)) +(setq p4_16-cppwarn-regexp (regexp-opt p4_16-cppwarn 1)) + + +;; create the list for font-lock. +;; each category of keyword is given a particular face +(defconst p4_16-font-lock-keywords + (list + (cons p4_16-cpp-regexp font-lock-preprocessor-face) + (cons p4_16-cppwarn-regexp font-lock-warning-face) + (cons p4_16-types-regexp font-lock-type-face) + (cons p4_16-constants-regexp font-lock-constant-face) + (cons p4_16-attributes-regexp font-lock-builtin-face) + (cons p4_16-variables-regexp font-lock-variable-name-face) + ;;; This is a special case to distinguish the method from the keyword + (cons "\\.apply" font-lock-function-name-face) + (cons p4_16-primitives-regexp font-lock-function-name-face) + (cons p4_16-operations-regexp font-lock-builtin-face) + (cons p4_16-keywords-regexp font-lock-keyword-face) + (cons p4_16-annotations-regexp font-lock-keyword-face) + (cons "\\(\\w*_t +\\)" font-lock-type-face) + (cons "[^A-Z_][A-Z] " font-lock-type-face) ;; Total hack for templates + (cons "<[A-Z, ]*>" font-lock-type-face) + (cons "\\(<[^>]+>\\)" font-lock-string-face) + (cons "\\([^_A-Za-z]\\([0-9]+w\\)?0x[0-9A-Fa-f]+\\)" font-lock-constant-face) + (cons "\\([^_A-Za-z]\\([0-9]+w\\)?0b[01]+\\)" font-lock-constant-face) + (cons "\\([^_A-Za-z][+-]?\\([0-9]+w\\)?[0-9]+\\)" font-lock-constant-face) + ;;(cons "\\(\\w*\\)" font-lock-variable-name-face) + ) + "Default Highlighting Expressions for P4_16") + +(defvar p4_16-mode-syntax-table + (let ((st (make-syntax-table))) + (modify-syntax-entry ?_ "w" st) + (modify-syntax-entry ?/ ". 124b" st) + (modify-syntax-entry ?* ". 23" st) + (modify-syntax-entry ?\n "> b" st) + st) + "Syntax table for p4_16-mode") + +;;; Indentation +(defvar p4_16-indent-offset 4 + "Indentation offset for `p4_16-mode'.") + +(defun p4_16-indent-line () + "Indent current line for any balanced-paren-mode'." + (interactive) + (let ((indent-col 0) + (indentation-increasers "[{(]") + (indentation-decreasers "[})]") + ) + (save-excursion + (beginning-of-line) + (condition-case nil + (while t + (backward-up-list 1) + (when (looking-at indentation-increasers) + (setq indent-col (+ indent-col p4_16-indent-offset)))) + (error nil))) + (save-excursion + (back-to-indentation) + (when (and (looking-at indentation-decreasers) + (>= indent-col p4_16-indent-offset)) + (setq indent-col (- indent-col p4_16-indent-offset)))) + (indent-line-to indent-col))) + +;;; Imenu support +(require 'imenu) +(setq p4_16-imenu-generic-expression + '( + ("Controls" "^ *control +\\([A-Za-z0-9_]*\\)" 1) + ("Externs" "^ *extern +\\([A-Za-z0-9_]*\\) *\\([A-Za-z0-9_]*\\)" 2) + ("Tables" "^ *table +\\([A-Za-z0-9_]*\\)" 1) + ("Actions" "^ *action +\\([A-Za-z0-9_]*\\)" 1) + ("Parsers" "^ *parser +\\([A-Za-z0-9_]*\\)" 1) + ("Parser States" "^ *state +\\([A-Za-z0-9_]*\\)" 1) + ("Headers" "^ *header +\\([A-Za-z0-9_]*\\)" 1) + ("Header Unions" "^ *header_union +\\([A-Za-z0-9_]*\\)" 1) + ("Structs" "^ *struct +\\([A-Za-z0-9_]*\\)" 1) + )) + +;;; Cscope Support +(require 'xcscope) + +;; Put everything together +(defun p4_16-mode () + "Major mode for editing P4_16 programs" + (interactive) + (kill-all-local-variables) + (set-syntax-table p4_16-mode-syntax-table) + (use-local-map p4_16-mode-map) + (set (make-local-variable 'font-lock-defaults) '(p4_16-font-lock-keywords)) + (set (make-local-variable 'indent-line-function) 'p4_16-indent-line) + (setq major-mode 'p4_16-mode) + (setq mode-name "P4_16") + (setq imenu-generic-expression p4_16-imenu-generic-expression) + (imenu-add-to-menubar "P4_16") + (cscope-minor-mode) + (run-hooks 'p4_16-mode-hook) +) + +;; The most important line +(provide 'p4_16-mode) diff --git a/init.el b/init.el index 84e7adc..916569b 100644 --- a/init.el +++ b/init.el @@ -26,9 +26,8 @@ '("melpa" . "https://melpa.org/packages/") t) (package-initialize) - ;; Local copies of packages no longer provided by MELPA. See - ;; https://github.com/melpa/melpa/pull/5008. - (add-to-list 'load-path "~/.emacs.d/emacswiki/") + ;; External .el files that are not available from MELPA. + (add-to-list 'load-path "~/.emacs.d/external/") ;; -------------------------------------------------------------------------- ;; Load `emodule'. diff --git a/modules/languages.el b/modules/languages.el index c080f3d..e4871b7 100644 --- a/modules/languages.el +++ b/modules/languages.el @@ -25,6 +25,10 @@ ccls ;; Dockerfile dockerfile-mode + ;; P4 + xcscope + ;; Protobuf + protobuf-mode ;; Python pyvenv cython-mode @@ -63,6 +67,13 @@ (use-package dockerfile-mode :defer t) + ;; -------------------------------------------------------------------------- + ;; kOS. + ;; -------------------------------------------------------------------------- + + (use-package kos-mode + :mode "\\.ks\\'") + ;; -------------------------------------------------------------------------- ;; LaTeX. ;; -------------------------------------------------------------------------- @@ -75,6 +86,21 @@ (add-hook 'makefile-mode-hook (lambda () (setq indent-tabs-mode t))) + ;; -------------------------------------------------------------------------- + ;; P4. + ;; -------------------------------------------------------------------------- + + ;; Note needs xcscope + (use-package p4_16-mode + :mode "\\.p4\\'") + + ;; -------------------------------------------------------------------------- + ;; Protobuf. + ;; -------------------------------------------------------------------------- + + (use-package protobuf-mode + :defer t) + ;; -------------------------------------------------------------------------- ;; Python. ;; --------------------------------------------------------------------------