commit 33cca60d5aed297c5967e123618737b463fb64e7 Author: d6 Date: Tue May 3 18:30:29 2022 -0400 initial import diff --git a/.hgignore b/.hgignore new file mode 100644 index 0000000..e4f53f5 --- /dev/null +++ b/.hgignore @@ -0,0 +1,8 @@ +# use glob syntax. +syntax: glob +auto-save-list +elpa +emms +straight +transient +*~ diff --git a/init.el b/init.el new file mode 100644 index 0000000..9053ea0 --- /dev/null +++ b/init.el @@ -0,0 +1,366 @@ +;; set up straight.el +(defvar bootstrap-version) +(let ((bootstrap-file + (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory)) + (bootstrap-version 5)) + (unless (file-exists-p bootstrap-file) + (with-current-buffer + (url-retrieve-synchronously + "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el" + 'silent 'inhibit-cookies) + (goto-char (point-max)) + (eval-print-last-sexp))) + (load bootstrap-file nil 'nomessage)) + +;; set a bunch of varibles +(setq user-full-name "d_m" + user-mail-address "d_m@plastic-idolatry.com" + straight-use-package-by-default t + package-enable-at-startup nil + straight-vc-git-default-protocol 'https + load-path (cons "~/.emacs-new.d/lisp" load-path) + inhibit-startup-screen t + org-directory "~/org/" + line-move-visual nil + create-lockfiles nil + make-backup-files nil + column-number-mode t + scroll-error-top-bottom t + show-paren-delay 0.5 + column-number-mode t + diff-switches "-u" + large-file-warning-threshold nil + sentence-end-double-space nil + mode-line-compact nil + company-idle-delay nil + company-tooltip-idle-delay nil + dired-kill-when-opening-new-dired-buffer t + read-minibuffer-restore-windows t + frame-background-mode 'dark) + +;; turn off UI various gizmos +(set-face-attribute 'mode-line nil :box nil) +(when (fboundp 'scroll-bar-mode) (scroll-bar-mode -1)) +(when (fboundp 'tool-bar-mode) (tool-bar-mode -1)) +(when (fboundp 'menu-bar-mode) (menu-bar-mode -1)) +(blink-cursor-mode 0) + +;; install icons +(use-package all-the-icons + :if (display-graphic-p)) + +;; show function names in modeline +(which-function-mode t) + +;; use utf-8 +(prefer-coding-system 'utf-8) + +;; UI settings when not in a terminal +(when (display-graphic-p) + (setq mac-option-key-is-meta nil + mac-command-key-is-meta t + mac-command-modifier 'meta + mac-option-modifier nil + x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)) + (set-frame-font "PragmataPro Liga 28" nil t) + (set-foreground-color "#c7c7c7") + (set-background-color "#000000")) + +;; set up font ligatures +(use-package pragmatapro-lig + :straight (pragmatapro-lig :type git + :host github + :repo "lumiknit/emacs-pragmatapro-ligatures") + :config (add-hook 'prog-mode-hook 'pragmatapro-lig-mode)) + +;; line numbers +(global-display-line-numbers-mode t) +(setq display-line-numbers "%4d ") + +;; allow y or n instead of yes or no +(fset 'yes-or-no-p 'y-or-n-p) + +;; C-x p to get back to mark +(bind-key "C-x p" 'pop-to-mark-command) +(setq set-mark-command-repeat-pop t) + +;; work with multiple files not in same directory +(require 'find-dired) +(setq find-ls-option '("-print0 | xargs -0 ls -ld" . "-ld")) + +;; hippie expand stuff: M-/ to expand things +(bind-key "M-/" 'hippie-expand) +(defun sanityinc/dabbrev-friend-buffer (other-buffer) + (< (buffer-size other-buffer) (* 1 1024 1024))) +(setq dabbrev-friend-buffer-function 'sanityinc/dabbrev-friend-buffer) +(setq hippie-expand-try-functions-list + '(try-expand-all-abbrevs + try-complete-file-name-partially + try-complete-file-name + try-expand-dabbrev + try-expand-dabbrev-from-kill + try-expand-dabbrev-all-buffers + try-expand-list + try-expand-line + try-complete-lisp-symbol-partially + try-complete-lisp-symbol)) + +;; comment regions using C-c # (uncomment with C-u C-c #) +(global-set-key "\C-c#" 'comment-region) +(setq comment-empty-lines nil) + +;; indent regions using C-c > and C-c < +(global-set-key "\C-c>" 'indent-region) +(global-set-key "\C-c<" 'unindent-region) + +;; use M-g to go to a certain line +(global-set-key "\M-g" 'goto-line) + +;; use M-$ to do query-replace-regexp +(global-set-key "\M-$" 'query-replace-regexp) + +;; modes +(electric-indent-mode 0) + +;; global keybindings +(global-unset-key (kbd "C-z")) + +; synchronize emacs exec-path and $PATH +(use-package exec-path-from-shell + :config (when (memq window-system '(mac ns x)) + (exec-path-from-shell-initialize))) + +;; rainbow delimiters +(use-package rainbow-delimiters) + +;; distraction free writing +(use-package writeroom-mode) + +;; C-c restore old buffer view after popups +(use-package winner + :config (winner-mode 1)) + +;; compact mode line +(use-package smart-mode-line) + +;; various modes that might come in handy +(use-package markdown-mode) +(use-package racket-mode) +(use-package tuareg) +(use-package forth-mode) + +;; scala-mode +(use-package scala-mode + :mode "\\.s\\(cala\\|bt\\)$" + :interpreter ("scala" . scala-mode) + :config + (setq scala-indent:indent-value-expression nil + scala-indent:align-parameters nil + scala-indent:align-forms nil + scala-indent:use-javadoc-style t)) + +;; ;; Enable nice rendering of diagnostics like compile errors. +;; (use-package flycheck +;; :init (global-flycheck-mode)) +;; +;; (use-package lsp-mode +;; :ensure t) +;; ; :init (setq lsp-prefer-flymake nil)) +;; +;; (use-package lsp-ui +;; :ensure t +;; :hook (lsp-mode . lsp-ui-mode)) +;; +;; (use-package lsp-scala +;; :after scala-mode +;; :demand t +;; ; :hook (scala-mode . lsp) +;; :init (setq lsp-scala-server-command "~/bin/metals-emacs")) + +;; projectile +(use-package projectile + :demand + :init (setq projectile-use-git-grep t) + ;;;:config (projectile-global-mode t) + :bind (("C-c C-f" . projectile-find-file) + ("C-c C-g" . projectile-ripgrep))) + +;; ripgrep +(use-package rg) + +;; ido +(use-package flx-ido + :demand + :init (setq ido-show-dot-for-dired nil + ido-enable-dot-prefix nil + ido-use-faces t) + :config (ido-mode 1) + (ido-everywhere 1) + (flx-ido-mode 1)) + +;; highlight-symbol +(use-package highlight-symbol + :diminish highlight-symbol-mode + :commands highlight-symbol + :bind ("s-h" . highlight-symbol)) + +;; popup-imenu +(use-package popup-imenu + :commands popup-imenu + :bind ("M-i" . popup-imenu)) + +;; magit +(use-package magit + :commands magit-status magit-blame + :init (setq magit-revert-buffers nil) + :bind (("C-x g" . magit-status) + ("s-b" . magit-blame))) + +;; org roam +(use-package org-roam + :custom (org-roam-directory "~/org/")) + +;; git-gutter +(use-package git-gutter + :config (global-git-gutter-mode t) + (set-face-foreground 'git-gutter:modified "orange") + (set-face-foreground 'git-gutter:added "green") + (set-face-foreground 'git-gutter:deleted "red") + (setq git-gutter:handled-backends '(git hg svn)) + (global-set-key (kbd "C-x n") 'git-gutter:next-hunk)) + +;; git-timemachine +(use-package git-timemachine + :config (add-hook 'git-timemachine-mode-hook (lambda () (ensime-mode 0)))) + +;; json +(use-package json-mode) + +;; glauce +(require 'glauce-mode) + +;; uxntal +(use-package uxntal-mode + :straight (uxntal-mode :type git + :host github + :repo "non/uxntal-mode") + :bind ("C-c d" . uxntal-explain-word) + :config (setq uxntal-mode-strict-comments nil)) + +;; C-c C-c for M-x compile +(global-set-key "\C-c\C-c" 'compile) + +;; bazel +(use-package bazel + :straight (bazel :type git + :host github + :repo "bazelbuild/emacs-bazel-mode") + :bind ("C-c C-b" . bazel-build) + :config (setq bazel-command '("/usr/local/bin/bazel"))) + +;; thrift +(use-package thrift-mode + :straight (thrift-mode :type git + :host github + :repo "davidmiller/thrift-mode") + :config (add-to-list 'auto-mode-alist '("\\.thrift\\'" . thrift-mode))) + +;; use doom themes )) +(use-package doom-themes )) + :straight (doom-themes :type git )) + :host github )) + :repo "doomemacs/themes") )) + :config (load-theme 'doom-badger t) )) + (doom-themes-neotree-config) )) + (setq doom-themes-treemacs-theme "doom-colors") )) + (doom-themes-treemacs-config) )) + (doom-themes-org-config)) )) + +;; try using a fancier mode line +(use-package doom-modeline + :ensure t + :init (doom-modeline-mode 1) + :config + (setq doom-modeline-height 1 + doom-modeline-buffer-file-name-style 'truncate-with-project + ;doom-modeline-buffer-file-name-style 'relative-to-project + doom-modeline-buffer-encoding nil) + (display-battery-mode 1)) + +;;; turn off branch in mode line for now +;(setq vc-handled-backends nil) + +;; force vc to update branches, etc. (unused for now) +(defun force-update-vcs () + "Update vc in all verson-controlled buffers" + (interactive) + (dolist (buf (buffer-list)) + (with-current-buffer buf + (vc-refresh-state)))) + +;; playing music in emacs +(use-package emms + :config + (setq emms-source-file-default-directory "~/bandcamp/" + emms-browser-covers 'emms-browser-cache-thumbnail-async + scroll-up-aggressively 0.0 + scroll-down-aggressively 0.0 + emms-playlist-buffer-name "*Music*") + (emms-all) + (emms-default-players)) + +;; browsing gemini/gopher sites in emacs +(use-package elpher + :config + (setq elpher-default-url-type "gemini://")) + +;; local copy in .emacs.d/lisp +(require 'etags-select) + +;; don't case fold for ctags +(setq tags-case-fold-search nil) + +;; whitespace stuff +(require 'whitespace) +(global-whitespace-mode t) +(setq whitespace-style '(newline tab-mark)) +(setq-default indent-tabs-mode nil + tab-width 4 + c-basic-offset 4 + show-trailing-whitespace t) + +;; handy function to toggle tabs +(defun toggle-indent-tabs () + "Toggle tabs on/off" + (interactive) + (setq indent-tabs-mode (if (indent-tabs-mode) nil t))) + +;; handy function to regenerate tags +(defun regenerate-tags () + "regenerate-tags" + (interactive) + (defun runloop (dir) + (let ((tagfile (concat dir "TAGS"))) + (if (file-exists-p tagfile) + (let ((default-directory dir)) + (progn + (shell-command "echo generating tags...") + (async-shell-command "ets"))) + (progn + (let ((next (file-name-directory (directory-file-name dir)))) + (if (equal dir next) (shell-command "uptime") (runloop next))))))) + (runloop default-directory)) +(global-set-key (kbd "C-t") 'regenerate-tags) + +;; spell checking as you type in text-mode +(autoload 'flyspell-mode-on "flyspell" "On-the-fly ispell." t) +(add-hook 'text-mode-hook 'flyspell-mode-on) + +;; use nicer diff colors +(defun update-diff-colors () + "update the colors for diff faces" + (set-face-foreground 'diff-added "green") + (set-face-foreground 'diff-removed "red") + (set-face-foreground 'diff-changed "purple")) +(eval-after-load "diff-mode" + '(update-diff-colors)) diff --git a/lisp/etags-select.el b/lisp/etags-select.el new file mode 100644 index 0000000..aed25e9 --- /dev/null +++ b/lisp/etags-select.el @@ -0,0 +1,477 @@ +;;; etags-select.el --- Select from multiple tags + +;; Copyright (C) 2007 Scott Frazer + +;; Author: Scott Frazer +;; Maintainer: Scott Frazer +;; Created: 07 Jun 2007 +;; Version: 1.13 +;; Keywords: etags tags tag select + +;; This file is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This file is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; Open a buffer with file/lines of exact-match tags shown. Select one by +;; going to a line and pressing return. pop-tag-mark still works with this +;; code. +;; +;; If there is only one match, you can skip opening the selection window by +;; setting a custom variable. This means you could substitute the key binding +;; for find-tag-at-point with etags-select-find-tag-at-point, although it +;; won't play well with tags-loop-continue. On the other hand, if you like +;; the behavior of tags-loop-continue you probably don't need this code. +;; +;; I use this: +;; (global-set-key "\M-?" 'etags-select-find-tag-at-point) +;; (global-set-key "\M-." 'etags-select-find-tag) +;; +;; Contributers of ideas and/or code: +;; David Engster +;; James Ferguson +;; +;;; Change log: +;; +;; 28 Oct 2008 -- v1.13 +;; Add short tag name completion option +;; Add go-if-tagnum-is-unambiguous option +;; 13 May 2008 -- v1.12 +;; Fix completion bug for XEmacs etags +;; Add highlighting of tag after jump +;; 28 Apr 2008 -- v1.11 +;; Add tag completion +;; 25 Sep 2007 -- v1.10 +;; Fix save window layout bug +;; 25 Sep 2007 -- v1.9 +;; Add function to prompt for tag to find (instead of using +;; what is at point) +;; 25 Sep 2007 -- v1.8 +;; Don't mess up user's window layout. +;; Add function/binding to go to the tag in other window. +;; 10 Sep 2007 -- v1.7 +;; Disambiguate tags with matching suffixes +;; 04 Sep 2007 -- v1.6 +;; Speed up tag searching +;; 27 Jul 2007 -- v1.5 +;; Respect case-fold-search and tags-case-fold-search +;; 24 Jul 2007 -- v1.4 +;; Fix filenames for tag files with absolute paths +;; 24 Jul 2007 -- v1.3 +;; Handle qualified and implicit tags. +;; Add tag name to display. +;; Add tag numbers so you can jump directly to one. +;; 13 Jun 2007 -- v1.2 +;; Need to regexp-quote the searched-for string. + +;;; Code: + +(require 'custom) +(require 'etags) + +;;; Custom stuff + +;;;###autoload +(defgroup etags-select-mode nil + "*etags select mode." + :group 'etags) + +;;;###autoload +(defcustom etags-select-no-select-for-one-match t + "*If non-nil, don't open the selection window if there is only one +matching tag." + :group 'etags-select-mode + :type 'boolean) + +;;;###autoload +(defcustom etags-select-mode-hook nil + "*List of functions to call on entry to etags-select-mode mode." + :group 'etags-select-mode + :type 'hook) + +;;;###autoload +(defcustom etags-select-highlight-tag-after-jump t + "*If non-nil, temporarily highlight the tag after you jump to it." + :group 'etags-select-mode + :type 'boolean) + +;;;###autoload +(defcustom etags-select-highlight-delay 1.0 + "*How long to highlight the tag." + :group 'etags-select-mode + :type 'number) + +;;;###autoload +(defface etags-select-highlight-tag-face + '((t (:foreground "white" :background "cadetblue4" :bold t))) + "Font Lock mode face used to highlight tags." + :group 'etags-select-mode) + +;;;###autoload +(defcustom etags-select-use-short-name-completion nil + "*Use short tag names during completion. For example, say you +have a function named foobar in several classes and you invoke +`etags-select-find-tag'. If this variable is nil, you would have +to type ClassA::foo to start completion. Since avoiding +knowing which class a function is in is the basic idea of this +package, if you set this to t you can just type foo. + +Only works with GNU Emacs." + :group 'etags-select-mode + :type 'boolean) + +;;;###autoload +(defcustom etags-select-go-if-unambiguous nil + "*If non-nil, jump by tag number if it is unambiguous." + :group 'etags-select-mode + :type 'boolean) + + ;;; Variables + +(defvar etags-select-buffer-name "*etags-select*" + "etags-select buffer name.") + +(defvar etags-select-mode-font-lock-keywords nil + "etags-select font-lock-keywords.") + +(defvar etags-select-source-buffer nil + "etags-select source buffer tag was found from.") + +(defvar etags-select-opened-window nil + "etags-select opened a select window.") + +(defconst etags-select-non-tag-regexp "\\(\\s-*$\\|In:\\|Finding tag:\\)" + "etags-select non-tag regex.") + +;;; Functions + +(if (string-match "XEmacs" emacs-version) + (fset 'etags-select-match-string 'match-string) + (fset 'etags-select-match-string 'match-string-no-properties)) + +;; I use Emacs, but with a hacked version of XEmacs' etags.el, thus this variable + +(defvar etags-select-use-xemacs-etags-p (fboundp 'get-tag-table-buffer) + "Use XEmacs etags?") + +(defun etags-select-case-fold-search () + "Get case-fold search." + (when (boundp 'tags-case-fold-search) + (if (memq tags-case-fold-search '(nil t)) + tags-case-fold-search + case-fold-search))) + +(defun etags-select-insert-matches (tagname tag-file tag-count) + "Insert matches to tagname in tag-file." + (let ((tag-table-buffer (etags-select-get-tag-table-buffer tag-file)) + (tag-file-path (file-name-directory tag-file)) + (tag-regex (concat "^.*?\\(" "\^?\\(.+[:.']" tagname "\\)\^A" + "\\|" "\^?" tagname "\^A" + "\\|" "\\<" tagname "[ \f\t()=,;]*\^?[0-9,]" + "\\)")) + (case-fold-search (etags-select-case-fold-search)) + full-tagname tag-line filename current-filename) + (set-buffer tag-table-buffer) + (modify-syntax-entry ?_ "w") + (goto-char (point-min)) + (while (search-forward tagname nil t) + (beginning-of-line) + (when (re-search-forward tag-regex (point-at-eol) 'goto-eol) + (setq full-tagname (or (etags-select-match-string 2) tagname)) + (setq tag-count (1+ tag-count)) + (beginning-of-line) + (re-search-forward "\\s-*\\(.*?\\)\\s-*\^?") + (setq tag-line (etags-select-match-string 1)) + (end-of-line) + (save-excursion + (re-search-backward "\f") + (re-search-forward "^\\(.*?\\),") + (setq filename (etags-select-match-string 1)) + (unless (file-name-absolute-p filename) + (setq filename (concat tag-file-path filename)))) + (save-excursion + (set-buffer etags-select-buffer-name) + (when (not (string= filename current-filename)) + (insert "\nIn: " filename "\n") + (setq current-filename filename)) + (insert (int-to-string tag-count) " [" full-tagname "] " tag-line "\n")))) + (modify-syntax-entry ?_ "_") + tag-count)) + +(defun etags-select-get-tag-table-buffer (tag-file) + "Get tag table buffer for a tag file." + (if etags-select-use-xemacs-etags-p + (get-tag-table-buffer tag-file) + (visit-tags-table-buffer tag-file) + (get-file-buffer tag-file))) + +;;;###autoload +(defun etags-select-find-tag-at-point () + "Do a find-tag-at-point, and display all exact matches. If only one match is +found, see the `etags-select-no-select-for-one-match' variable to decide what +to do." + (interactive) + (etags-select-find (find-tag-default))) + +;;;###autoload +(defun etags-select-find-tag () + "Do a find-tag, and display all exact matches. If only one match is +found, see the `etags-select-no-select-for-one-match' variable to decide what +to do." + (interactive) + (setq etags-select-source-buffer (buffer-name)) + (let* ((default (find-tag-default)) + (tagname (completing-read + (format "Find tag (default %s): " default) + 'etags-select-complete-tag nil nil nil 'find-tag-history default))) + (etags-select-find tagname))) + +(defun etags-select-complete-tag (string predicate what) + "Tag completion." + (etags-select-build-completion-table) + (if (eq what t) + (all-completions string (etags-select-get-completion-table) predicate) + (try-completion string (etags-select-get-completion-table) predicate))) + +(defun etags-select-build-completion-table () + "Build tag completion table." + (save-excursion + (set-buffer etags-select-source-buffer) + (let ((tag-files (etags-select-get-tag-files))) + (mapcar (lambda (tag-file) (etags-select-get-tag-table-buffer tag-file)) tag-files)))) + +(defun etags-select-get-tag-files () + "Get tag files." + (if etags-select-use-xemacs-etags-p + (buffer-tag-table-list) + (mapcar 'tags-expand-table-name tags-table-list))) + +(defun etags-select-get-completion-table () + "Get the tag completion table." + (if etags-select-use-xemacs-etags-p + tag-completion-table + (tags-completion-table))) + +(defun etags-select-tags-completion-table-function () + "Short tag name completion." + (let ((table (make-vector 16383 0)) + (tag-regex "^.*?\\(\^?\\(.+\\)\^A\\|\\<\\(.+\\)[ \f\t()=,;]*\^?[0-9,]\\)") + (progress-reporter + (make-progress-reporter + (format "Making tags completion table for %s..." buffer-file-name) + (point-min) (point-max)))) + (save-excursion + (goto-char (point-min)) + (while (not (eobp)) + (when (looking-at tag-regex) + (intern (replace-regexp-in-string ".*[:.']" "" (or (match-string 2) (match-string 3))) table)) + (forward-line 1) + (progress-reporter-update progress-reporter (point)))) + table)) + +(unless etags-select-use-xemacs-etags-p + (defadvice etags-recognize-tags-table (after etags-select-short-name-completion activate) + "Turn on short tag name completion (maybe)" + (when etags-select-use-short-name-completion + (setq tags-completion-table-function 'etags-select-tags-completion-table-function)))) + +(defun etags-select-find (tagname) + "Core tag finding function." + (let ((tag-files (etags-select-get-tag-files)) + (tag-count 0)) + (setq etags-select-source-buffer (buffer-name)) + (get-buffer-create etags-select-buffer-name) + (set-buffer etags-select-buffer-name) + (setq buffer-read-only nil) + (erase-buffer) + (insert "Finding tag: " tagname "\n") + (mapcar (lambda (tag-file) + (setq tag-count (etags-select-insert-matches tagname tag-file tag-count))) + tag-files) + (cond ((= tag-count 0) + (message (concat "No matches for tag \"" tagname "\"")) + (ding)) + ((and (= tag-count 1) etags-select-no-select-for-one-match) + (setq etags-select-opened-window nil) + (set-buffer etags-select-buffer-name) + (goto-char (point-min)) + (etags-select-next-tag) + (etags-select-goto-tag)) + (t + (set-buffer etags-select-buffer-name) + (goto-char (point-min)) + (etags-select-next-tag) + (set-buffer-modified-p nil) + (setq buffer-read-only t) + (setq etags-select-opened-window (selected-window)) + (select-window (split-window-vertically)) + (switch-to-buffer etags-select-buffer-name) + (etags-select-mode tagname))))) + +(defun etags-select-goto-tag (&optional arg other-window) + "Goto the file/line of the tag under the cursor. +Use the C-u prefix to prevent the etags-select window from closing." + (interactive "P") + (let ((case-fold-search (etags-select-case-fold-search)) + tagname tag-point text-to-search-for filename filename-point (search-count 1)) + (save-excursion + (goto-char (point-min)) + (re-search-forward "Finding tag: \\(.*\\)$") + (setq tagname (etags-select-match-string 1))) + (beginning-of-line) + (if (looking-at etags-select-non-tag-regexp) + (message "Please put the cursor on a line with the tag.") + (setq tag-point (point)) + (setq overlay-arrow-position (point-marker)) + (re-search-forward "\\]\\s-+\\(.+?\\)\\s-*$") + (setq text-to-search-for (regexp-quote (etags-select-match-string 1))) + (goto-char tag-point) + (re-search-backward "^In: \\(.*\\)$") + (setq filename (etags-select-match-string 1)) + (setq filename-point (point)) + (goto-char tag-point) + (while (re-search-backward (concat "^.*?\\]\\s-+" text-to-search-for) filename-point t) + (setq search-count (1+ search-count))) + (goto-char tag-point) + (unless arg + (kill-buffer etags-select-buffer-name) + (when etags-select-opened-window + (delete-window (selected-window)) + (select-window etags-select-opened-window))) + (switch-to-buffer etags-select-source-buffer) + (if etags-select-use-xemacs-etags-p + (push-tag-mark) + (ring-insert find-tag-marker-ring (point-marker))) + (if other-window + (find-file-other-window filename) + (find-file filename)) + (goto-char (point-min)) + (while (> search-count 0) + (unless (re-search-forward (concat "^\\s-*" text-to-search-for) nil t) + (message "TAGS file out of date ... stopping at closest match") + (setq search-count 1)) + (setq search-count (1- search-count))) + (beginning-of-line) + (re-search-forward tagname) + (goto-char (match-beginning 0)) + (when etags-select-highlight-tag-after-jump + (etags-select-highlight (match-beginning 0) (match-end 0)))))) + +(defun etags-select-highlight (beg end) + "Highlight a region temporarily." + (if (featurep 'xemacs) + (let ((extent (make-extent beg end))) + (set-extent-property extent 'face 'etags-select-highlight-tag-face) + (sit-for etags-select-highlight-delay) + (delete-extent extent)) + (let ((ov (make-overlay beg end))) + (overlay-put ov 'face 'etags-select-highlight-tag-face) + (sit-for etags-select-highlight-delay) + (delete-overlay ov)))) + +(defun etags-select-goto-tag-other-window (&optional arg) + "Goto the file/line of the tag under the cursor in other window. +Use the C-u prefix to prevent the etags-select window from closing." + (interactive "P") + (etags-select-goto-tag arg t)) + +(defun etags-select-next-tag () + "Move to next tag in buffer." + (interactive) + (beginning-of-line) + (when (not (eobp)) + (forward-line)) + (while (and (looking-at etags-select-non-tag-regexp) (not (eobp))) + (forward-line)) + (when (eobp) + (ding))) + +(defun etags-select-previous-tag () + "Move to previous tag in buffer." + (interactive) + (beginning-of-line) + (when (not (bobp)) + (forward-line -1)) + (while (and (looking-at etags-select-non-tag-regexp) (not (bobp))) + (forward-line -1)) + (when (bobp) + (ding))) + +(defun etags-select-quit () + "Quit etags-select buffer." + (interactive) + (kill-buffer nil) + (delete-window)) + +(defun etags-select-by-tag-number (first-digit) + "Select a tag by number." + (let ((current-point (point)) tag-num) + (if (and etags-select-go-if-unambiguous (not (re-search-forward (concat "^" first-digit) nil t 2))) + (setq tag-num first-digit) + (setq tag-num (read-from-minibuffer "Tag number? " first-digit))) + (goto-char (point-min)) + (if (re-search-forward (concat "^" tag-num) nil t) + (etags-select-goto-tag) + (goto-char current-point) + (message (concat "Couldn't find tag number " tag-num)) + (ding)))) + +;;; Keymap + +(defvar etags-select-mode-map nil "'etags-select-mode' keymap.") +(if (not etags-select-mode-map) + (let ((map (make-keymap))) + (define-key map [(return)] 'etags-select-goto-tag) + (define-key map [(meta return)] 'etags-select-goto-tag-other-window) + (define-key map [(down)] 'etags-select-next-tag) + (define-key map [(up)] 'etags-select-previous-tag) + (define-key map "n" 'etags-select-next-tag) + (define-key map "p" 'etags-select-previous-tag) + (define-key map "q" 'etags-select-quit) + (define-key map "0" (lambda () (interactive) (etags-select-by-tag-number "0"))) + (define-key map "1" (lambda () (interactive) (etags-select-by-tag-number "1"))) + (define-key map "2" (lambda () (interactive) (etags-select-by-tag-number "2"))) + (define-key map "3" (lambda () (interactive) (etags-select-by-tag-number "3"))) + (define-key map "4" (lambda () (interactive) (etags-select-by-tag-number "4"))) + (define-key map "5" (lambda () (interactive) (etags-select-by-tag-number "5"))) + (define-key map "6" (lambda () (interactive) (etags-select-by-tag-number "6"))) + (define-key map "7" (lambda () (interactive) (etags-select-by-tag-number "7"))) + (define-key map "8" (lambda () (interactive) (etags-select-by-tag-number "8"))) + (define-key map "9" (lambda () (interactive) (etags-select-by-tag-number "9"))) + (setq etags-select-mode-map map))) + +;;; Mode startup + +(defun etags-select-mode (tagname) + "etags-select-mode is a mode for browsing through tags.\n\n +\\{etags-select-mode-map}" + (interactive) + (kill-all-local-variables) + (setq major-mode 'etags-select-mode) + (setq mode-name "etags-select") + (set-syntax-table text-mode-syntax-table) + (use-local-map etags-select-mode-map) + (make-local-variable 'font-lock-defaults) + (setq etags-select-mode-font-lock-keywords + (list (list "^\\(Finding tag:\\)" '(1 font-lock-keyword-face)) + (list "^\\(In:\\) \\(.*\\)" '(1 font-lock-keyword-face) '(2 font-lock-string-face)) + (list "^[0-9]+ \\[\\(.+?\\)\\]" '(1 font-lock-type-face)) + (list tagname '(0 font-lock-function-name-face)))) + (setq font-lock-defaults '(etags-select-mode-font-lock-keywords)) + (setq overlay-arrow-position nil) + (run-hooks 'etags-select-mode-hook)) + +(provide 'etags-select) +;;; etags-select.el ends here diff --git a/lisp/glauce-mode.el b/lisp/glauce-mode.el new file mode 100644 index 0000000..8607db4 --- /dev/null +++ b/lisp/glauce-mode.el @@ -0,0 +1,67 @@ +(require 'rx) + +(defvar glauce-mode-hook nil) + +(add-to-list 'auto-mode-alist '("\\.glc\\'" . glauce-mode)) + +(defconst glauce-mode-comment1-re + (rx (group "//" (0+ not-newline)))) + +(defconst glauce-mode-comment2-re + (rx (group "/\*" (0+ anything) "\*/"))) + +(defconst glauce-mode-type-re + (rx (group (in "A-Z") (0+ (in "A-Za-z0-9_"))))) + +(defconst glauce-mode-param-re + (rx (group (in "a-z") (0+ (in "A-Za-z0-9_"))))) + +(defconst glauce-mode-string-re + (rx (group "\"" + (0+ (or (not (any ?\\ ?\")) + (and "\\" (in "\"\\/bfnrt")) + (and "\\u" (repeat 4 (in "0-9a-fA-F"))))) + "\""))) + +(defconst glauce-mode-number-re + (rx (group + (or (and (in "1-9") (0+ (in "0-9"))) "0") + (\? (and "." (1+ (in "0-9")))) + (\? (in "eE") (\? (in "+-")) (1+ (in "0-9")))))) + +(defconst glauce-mode-keyword-re + (rx (group (or "true" "false" "null" + "package" "import" "assert" "with" + "subsetOf" "properSubsetOf" + "supersetOf" "properSupersetOf" + "disjointFrom" "intersects")))) + +(defconst glauce-font-lock-keywords-1 + (list + (list glauce-mode-string-re 1 font-lock-string-face) + (list glauce-mode-keyword-re 1 font-lock-keyword-face) + (list glauce-mode-type-re 1 font-lock-type-face) + (list glauce-mode-param-re 1 font-lock-variable-name-face) + (list glauce-mode-number-re 1 font-lock-constant-face)) + "Level one font lock.") + +(defvar glauce-mode-syntax-table + (let ((table (make-syntax-table))) + (modify-syntax-entry ?/ ". 124b" table) + (modify-syntax-entry ?* ". 23b" table) + table) + "Syntax table in use in `glauce-mode' buffers.") + +(defun glauce-mode () + "Major mode for editing Glauce files" + (interactive) + (kill-all-local-variables) + (set-syntax-table glauce-mode-syntax-table) + (set (make-local-variable 'font-lock-defaults) '(glauce-font-lock-keywords-1 nil nil)) + (setq major-mode 'glauce-mode) + (make-local-variable 'comment-start) + (setq comment-start "//") + (setq mode-name "Glauce") + (run-hooks 'glauce-mode-hook)) + +(provide 'glauce-mode)