This commit is contained in:
John Doty 2021-08-16 16:30:19 -07:00
parent 3e1c7b565b
commit f1a4519507
3 changed files with 498 additions and 6 deletions

View file

@ -17,9 +17,9 @@
'(comint-prompt-read-only t)
'(comint-scroll-to-bottom-on-input t)
'(company-backends
'(company-bbdb company-nxml company-css company-semantic company-clang company-cmake company-capf company-files
(company-dabbrev-code company-gtags company-etags company-keywords)
company-oddmuse company-dabbrev company-flow))
'(company-tasks company-reviewers company-bbdb company-nxml company-css company-capf
(company-dabbrev-code company-keywords)))
'(company-minimum-prefix-length 1)
'(css-indent-offset 2)
'(custom-safe-themes
'("3dbb18bf06f41012d4525e6c64c392d6cfef06a2f8fe1bf7b565c4e020255466" "8db4b03b9ae654d4a57804286eb3e332725c84d7cdab38463cb6b97d5762ad26" default))
@ -58,7 +58,7 @@
'(org-odd-levels-only t)
'(org-todo-keywords '((sequence "TODO" "|" "DONE" "ABANDONED" "DEFERRED")))
'(package-selected-packages
'(prettier-js zig-mode modus-operandi-theme esup gnu-elpa-keyring-update lsp-hack hack-mode rust-mode filladapt lsp-ui yaml-mode wgrep fsharp-mode company-lsp cquery mustache-mode clang-format projectile dash-functional mocha add-node-modules-path rjsx-mode xref-js2 js2-refactor company omnisharp geiser cider clojure-mode graphviz-dot-mode multi-term xterm-color thrift markdown-mode tuareg merlin ag use-package flycheck dockerfile-mode js2-mode web-mode tss switch-window python-mode paredit magit lua-mode go-mode go-autocomplete exec-path-from-shell csharp-mode color-theme-monokai auto-complete auto-complete-nxml flymake flyspell json-mode popup ruby-mode company-jedi tide elm-mode monky))
'(eglot prettier-js zig-mode modus-operandi-theme esup gnu-elpa-keyring-update lsp-hack hack-mode rust-mode filladapt lsp-ui yaml-mode wgrep fsharp-mode company-lsp cquery mustache-mode clang-format projectile dash-functional mocha add-node-modules-path rjsx-mode xref-js2 js2-refactor company omnisharp geiser cider clojure-mode graphviz-dot-mode multi-term xterm-color thrift markdown-mode tuareg merlin ag use-package flycheck dockerfile-mode js2-mode web-mode tss switch-window python-mode paredit magit lua-mode go-mode go-autocomplete exec-path-from-shell csharp-mode color-theme-monokai auto-complete auto-complete-nxml flymake flyspell json-mode popup ruby-mode company-jedi tide elm-mode monky))
'(reb-re-syntax 'string)
'(rmail-mail-new-frame t)
'(safe-local-variable-values
@ -84,8 +84,8 @@
'(tab-width 4)
'(tags-revert-without-query t)
'(tramp-completion-reread-directory-timeout nil)
'(tramp-default-method "sshx" nil (tramp))
'(tramp-use-ssh-controlmaster-options nil nil (tramp))
'(tramp-default-method "sshx")
'(tramp-use-ssh-controlmaster-options nil)
'(transient-mark-mode t)
'(truncate-lines t)
'(typescript-indent-level 2)

105
site-lisp/fb-glass.el Normal file
View file

@ -0,0 +1,105 @@
;;; fb-glass.el --- Emacs integration for the Glass CLI -*- lexical-binding: t; -*-
;; Keywords: tools,processes
;; Package-Requires: ((emacs "27.1") (f "1.0"))
;; Version: 0.1
;;; Commentary:
;; Integrates `glass` into Emacs. Improvements welcome!
;; Note that Glass is designed more for static/"offline" navigation of code, without needing
;; a full LSP to be running.
;; This integration will return stale results if you try to use it on files that have been modified.
;;; Code:
(require 'compile)
(require 'f)
(defun glass--call-process-shell-check-success (command)
(with-temp-buffer
(let ((exit-code (call-process-shell-command command nil (current-buffer))))
(unless (equal exit-code 0)
(error "Error running shell command"))
(buffer-string))))
(defun glass--root (filename)
"Gets the root corresponding to the given filename. If none given, the current buffer's filename is used."
(let ((default-directory (file-name-directory (file-truename filename))))
(string-trim (glass--call-process-shell-check-success "hg root"))))
(defun glass--repo (filename)
"Gets the Glean repo ID corresponding to the given filename. If none given, the current buffer's filename is used."
(let ((default-directory (file-name-directory (file-truename filename))))
(string-trim (glass--call-process-shell-check-success "hg config remotefilelog.reponame"))))
;;; VISIT SYMBOLS
(defun glass-visit-symbol (symbol)
"Given a Glass symbol, visit the file that defines that symbol"
(interactive)
(let* ((output (glass--call-process-shell-check-success
(format "glass --caller=emacs describe -t %s" (shell-quote-argument symbol))))
(position (split-string (car (split-string output)) ":"))
(filename (car position))
(local-filename (concat "~/" filename)))
(if (file-exists-p local-filename)
(progn
(find-file local-filename)
(goto-char (point-min))
(forward-line (- (string-to-number (cadr position)) 1))
(forward-char (- (string-to-number (caddr position)) 1)))
(let* ((buffer (generate-new-buffer (concat "glass--" (file-name-nondirectory filename))))
(repo (car (split-string filename "/")))
(exit-code (call-process "scsc" nil buffer nil
"cat"
"--repo" (shell-quote-argument repo)
"--path" (shell-quote-argument (string-remove-prefix repo filename))
"-B" "master")))
(if (equal exit-code 0)
(progn
(with-current-buffer buffer
(setq-local buffer-read-only t)
(goto-char (point-min))
(forward-line (- (string-to-number (cadr position)) 1))
(forward-char (- (string-to-number (caddr position)) 1)))
(pop-to-buffer buffer))
(progn
(kill-buffer buffer)
(error "Couldn't display source with `scsc`")))))))
;;; LIST SYMBOLS
(defun glass-list-symbols (&optional filename)
"Lists all symbols within the given filesystem path. If none given, the current buffer's filename is used."
(let* ((file (file-truename (or filename (buffer-file-name))))
(root (glass--root file))
(repo (glass--repo file))
(search-path (concat repo "/" (file-relative-name file root))))
;; TODO integrate with myles, myles to get a path -> glass to list its symbols
(compilation-start
(format "glass --caller emacs list-symbols %s | sed -e 's|^|~/|'" search-path))))
;;; SYMBOL-SEARCH
(with-eval-after-load "counsel"
(defun glass--symbol-search (input)
(counsel--async-command
(format "glass --caller=emacs symbol-search %s"
(shell-quote-argument input)))
nil)
(defun glass-symbol-search-counsel ()
"Find a symbol by full symbol ID prefix using `glass symbol-search`"
(interactive)
(counsel-require-program "glass")
(let ((default-directory (myles--root)))
;; TODO allow entering "/" to grab the current candidate and restart from there
;; similar to how it works for counsel-find-file
(ivy-read
"symbol prefix: "
#'glass--symbol-search
:caller 'glass-counsel
:dynamic-collection t
:action #'glass-visit-symbol))))
(provide 'fb-glass)
;;; fb-glass.el ends here

387
site-lisp/thrift.el Normal file
View file

@ -0,0 +1,387 @@
;;; thrift.el --- major mode for fbthrift and Apache Thrift files -*- lexical-binding: t; -*-
;; Keywords: languages
;; Package-Version: 20180905.1050
;; Package-Requires: ((emacs "24"))
;; Licensed to the Apache Software Foundation (ASF) under one
;; or more contributor license agreements. See the NOTICE file
;; distributed with this work for additional information
;; regarding copyright ownership. The ASF licenses this file
;; to you under the Apache License, Version 2.0 (the
;; "License"); you may not use this file except in compliance
;; with the License. You may obtain a copy of the License at
;;
;; http://www.apache.org/licenses/LICENSE-2.0
;;
;; Unless required by applicable law or agreed to in writing,
;; software distributed under the License is distributed on an
;; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
;; KIND, either express or implied. See the License for the
;; specific language governing permissions and limitations
;; under the License.
;;; Commentary:
;; This is a major mode for syntax highlighting .thrift files.
;;
;; Features:
;;
;; * Precise syntax highlighting based on the thrift parser code.
;; * Highlighting of method definitions
;; * Custom face for struct/argument indexes
;; * Highlighting of doxygen keywords
;; * Indentation
;;
;; This mode works for both fbthrift and Apache Thrift files.
;;
;; Hacked by doty for more modern thrift.
;;; Code:
(defvar thrift-mode-syntax-table
(let ((table (make-syntax-table)))
;; Both " and ' are strings.
(modify-syntax-entry ?\" "\"" table)
(modify-syntax-entry ?\\ "\\" table)
(modify-syntax-entry ?' "\"" table)
;; Treat < and > as paired delimiters.
(modify-syntax-entry ?< "(<" table)
(modify-syntax-entry ?> ")>" table)
;; Comments can start with //, /* or # characters.
(modify-syntax-entry ?/ ". 124" table)
(modify-syntax-entry ?* ". 23b" table)
(modify-syntax-entry ?# "<" table)
(modify-syntax-entry ?\n ">" table)
table))
(defgroup thrift nil
"A major mode for editing .thrift files."
:group 'languages)
(defface thrift-ordinal-face
'((t :foreground "orange"))
"Face used to highlight Thrift indexes."
:group 'thrift)
(defface thrift-doxygen-key-face
'((t :foreground "SlateGray"))
"Face used to highlight @foo in doxygen style comments."
:group 'thrift)
(defun thrift--doxygen-search (pattern limit)
"Search for PATTERN in /** comments, up to position LIMIT.
If we find a match, set match-data and put point on the final
location, and return point. Otherwise, return nil and don't move point.
This is intended to be used with `font-lock-keywords'."
(let (res
match-data)
(save-match-data
;; Search forward for the first @foo..
(while (and
(not res)
(re-search-forward pattern limit t))
;; Set match data to the @foo we found, before we call `looking-at'.
(setq match-data (match-data))
(let* ((ppss (syntax-ppss))
(in-comment-p (nth 4 ppss))
(comment-start (nth 8 ppss))
in-doxygen-comment-p)
;; Go to the start of the comment, and confirm this is a /** comment.
(when in-comment-p
(save-excursion
(goto-char comment-start)
(when (looking-at (rx "/**"))
(setq in-doxygen-comment-p t))))
(when in-doxygen-comment-p
(setq res (point))))))
;; Set match data and return point, so Emacs knows we found something.
(when res
(set-match-data match-data)
res)))
(defvar thrift-font-lock-keywords
`((,(regexp-opt
;; Useful keywords in thriftl.ll.
'("namespace"
"cpp_namespace"
"cpp_include"
"hs_include"
"java_package"
"cocoa_prefix"
"csharp_namespace"
"php_namespace"
"py_module"
"perl_package"
"ruby_namespace"
"smalltalk_category"
"smalltalk_prefix"
"include"
"oneway"
"typedef"
"struct"
"union"
"exception"
"extends"
"throws"
"service"
"enum"
"const"
"interaction" ;; doty
;; Deprecated
"cpp_type"
"async")
'symbols)
. font-lock-keyword-face)
;; Keywords in thriftl.ll that correspond to types.
(,(regexp-opt
'("binary"
"bool"
"byte"
"double"
"float"
"hash_map"
"hash_set"
"i16"
"i32"
"i64"
"list"
"map"
"set"
"slist"
"stream"
"string"
"void"
;; Treat optional/required as type keywords, as they occur in that context.
"optional"
"required"
)
'symbols)
. font-lock-type-face)
;; Reserved words in thirftl.ll that don't currently do anything.
(,(regexp-opt
'("abstract"
"and"
"args"
"as"
"assert"
"auto"
"break"
"case"
"char"
"class"
"continue"
"declare"
"def"
"default"
"del"
"delete"
"do"
"elif"
"else"
"elseif"
"except"
"exec"
"extern"
"finally"
"for"
"foreach"
"function"
"global"
"goto"
"if"
"implements"
"import"
"in"
"int"
"inline"
"instanceof"
"interface"
"is"
"lambda"
"long"
"native"
"new"
"not"
"or"
"pass"
"public"
"print"
"private"
"protected"
"raise"
"register"
"return"
"short"
"signed"
"sizeof"
"static"
"switch"
"synchronized"
"template"
"this"
"throw"
"transient"
"try"
"unsigned"
"var"
"virtual"
"volatile"
"while"
"with"
"yield"
"Object"
"Client"
"IFace"
"Processor")
'symbols)
. font-lock-type-face)
(,(regexp-opt
'("true" "false")
'symbols)
. font-lock-constant-face)
;; Constants are all in upper case, and cannot start with a
;; digit. We use font-lock-variable-name-face for consistence with
;; c-mode.
(,(rx symbol-start
(any upper "_")
(+ (any upper "_" digit))
symbol-end)
. font-lock-variable-name-face)
;; Highlight type declarations.
(,(rx symbol-start
(or "enum" "service" "struct" "interaction")
symbol-end
(+ space)
symbol-start
(*
(seq (syntax word) "."))
(group (+ (or (syntax word) (syntax symbol))))
symbol-end)
1 font-lock-type-face)
;; Highlight method declarations
(,(rx symbol-start
(group (+ (or (syntax word) (syntax symbol))))
symbol-end
"(")
1 font-lock-function-name-face)
;; Highlight other PascalCase symbols as types.
(,(rx symbol-start
(group
(any upper)
(+ (or (syntax word) (syntax symbol))))
symbol-end)
1 font-lock-type-face)
;; Highlight struct indexes.
(,(rx symbol-start
(group (+ digit))
symbol-end
":")
1 'thrift-ordinal-face)
;; Highlight doxygen items that are followed by a symbol, such as '@param foo_bar'.
(,(lambda (limit)
(thrift--doxygen-search
(rx (or "@param" "@throws") symbol-end
;; Highlight @param even before we've started typing the name of the param.
(zero-or-one
(1+ space)
(1+ (or (syntax word) (syntax symbol) ".")))
symbol-end)
limit))
0 'thrift-doxygen-key-face t)
;; Highlight standalone doxygen items.
(,(lambda (limit)
(thrift--doxygen-search
(rx (or "@return" "@see") symbol-end)
limit))
0 'thrift-doxygen-key-face t)))
(defvar thrift-indent-level 2
"Indentation amount used in Thrift files.")
(defun thrift-indent-line ()
"Indent the current line of Thrift code.
Preserves point position in the line where possible."
(interactive)
(let* ((point-offset (- (current-column) (current-indentation)))
(ppss (syntax-ppss (line-beginning-position)))
(paren-depth (nth 0 ppss))
(current-paren-pos (nth 1 ppss))
(text-after-paren
(when current-paren-pos
(save-excursion
(goto-char current-paren-pos)
(buffer-substring
(1+ current-paren-pos)
(line-end-position)))))
(in-multiline-comment-p (nth 4 ppss))
(current-line (buffer-substring (line-beginning-position) (line-end-position))))
;; If the current line is just a closing paren, unindent by one level.
(when (and
(not in-multiline-comment-p)
(string-match-p (rx bol (0+ space) (or ")" "}")) current-line))
(setq paren-depth (1- paren-depth)))
(cond
;; In multiline comments, ensure the leading * is indented by one
;; more space. For example:
;; /*
;; * <- this line
;; */
(in-multiline-comment-p
;; Don't modify lines that don't start with *, to avoid changing the indentation of commented-out code.
(when (or (string-match-p (rx bol (0+ space) "*") current-line)
(string= "" current-line))
(indent-line-to (1+ (* thrift-indent-level paren-depth)))))
;; Indent 'throws' lines by one extra level. For example:
;; void foo ()
;; throws (1: FooError fe)
((string-match-p (rx bol (0+ space) "throws" symbol-end) current-line)
(indent-line-to (* thrift-indent-level (1+ paren-depth))))
;; Indent according to the last paren position, if there is text
;; after the paren. For example:
;; throws (1: FooError fe,
;; 2: BarError be, <- this line
((and
text-after-paren
(not (string-match-p (rx bol (0+ space) eol) text-after-paren)))
(let (open-paren-column)
(save-excursion
(goto-char current-paren-pos)
(setq open-paren-column (current-column)))
(indent-line-to (1+ open-paren-column))))
;; Indent parameters by an extra level, so they're visually distinct from 'throws'.
;; void foo(
;; 1: int bar) <- this line
;; throws (1: FooError fe)
((and current-paren-pos
(eq (char-after current-paren-pos) ?\())
(indent-line-to (* thrift-indent-level (1+ paren-depth))))
;; Indent according to the amount of nesting.
(t
(indent-line-to (* thrift-indent-level paren-depth))))
;; Point is now at the beginning of indentation, restore it
;; to its original position (relative to indentation).
(when (>= point-offset 0)
(move-to-column (+ (current-indentation) point-offset)))))
;;;###autoload
(add-to-list 'auto-mode-alist '("\\.thrift$" . thrift-mode))
;;;###autoload
(define-derived-mode thrift-mode prog-mode "Thrift"
"Major mode for editing Thrift files."
(setq-local font-lock-defaults '(thrift-font-lock-keywords))
(setq-local indent-line-function 'thrift-indent-line)
(setq-local comment-start "// "))
(provide 'thrift)
;;; thrift.el ends here