From 0b0e95e88c1dbd6a9f16300ae03f725e37b6369b Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Thu, 28 Jul 2011 00:25:27 +0200 Subject: Preparing placing home-directory in repo --- emacs.d/elisp/csharp-mode.el | 1977 ------------------------------------------ 1 file changed, 1977 deletions(-) delete mode 100644 emacs.d/elisp/csharp-mode.el (limited to 'emacs.d/elisp/csharp-mode.el') diff --git a/emacs.d/elisp/csharp-mode.el b/emacs.d/elisp/csharp-mode.el deleted file mode 100644 index 9cd7914..0000000 --- a/emacs.d/elisp/csharp-mode.el +++ /dev/null @@ -1,1977 +0,0 @@ -;;; csharp-mode.el --- C# mode derived mode - -;; Author: Dylan R. E. Moonfire -;; Maintainer: Dylan R. E. Moonfire -;; Created: Feburary 2005 -;; Modified: February 2010 -;; Version: 0.7.4 - Dino Chiesa -;; Keywords: c# languages oop mode - -;; This program 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 of the License, or -;; (at your option) any later version. -;; -;; This program 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 this program; see the file COPYING. If not, write to -;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: -;; -;; This is a separate mode to implement the C# constructs and -;; font-locking. It is based on the java-mode example from cc-mode. -;; -;; csharp-mode requires CC Mode 5.30 or later. It works with -;; cc-mode 5.31.3, which is current at this time. -;; -;; Features: -;; -;; - font-lock and indent of C# syntax including: -;; all c# keywords and major syntax -;; attributes that decorate methods, classes, fields, properties -;; enum types -;; #if/#endif #region/#endregion -;; instance initializers -;; anonymous functions and methods -;; verbatim literal strings (those that begin with @) -;; generics -;; -;; - automagic code-doc generation when you type three slashes. -;; -;; - intelligent inserttion of matched pairs of curly braces. -;; -;; - sets the compiler regex for next-error, for csc.exe output. -;; -;; - - -;;; To use: -;; -;; put this in your .emacs: -;; -;; (autoload 'csharp-mode "csharp-mode" "Major mode for editing C# code." t) -;; -;; or: -;; -;; (require 'csharp-mode) -;; -;; -;; AND: -;; -;; (setq auto-mode-alist -;; (append '(("\\.cs$" . csharp-mode)) auto-mode-alist)) -;; (defun my-csharp-mode-fn () -;; "function that runs when csharp-mode is initialized for a buffer." -;; ...insert your code here... -;; ...most commonly, your custom key bindings ... -;; ) -;; (add-hook 'csharp-mode-hook 'my-csharp-mode-fn t) -;; -;; - - -;;; Bugs: -;; -;; Namespaces in the using statements are not fontified. Should do in -;; c-basic-matchers-before or c-basic-matchers-after. -;; -;; Method names with a preceding attribute are not fontified. -;; -;; Field/Prop names inside object initializers are fontified only -;; if the null constructor is used, with no parens. -;; -;; This code doesn't seem to work when you compile it, then -;; load/require in the emacs file. You will get an error (error -;; "`c-lang-defconst' must be used in a file") which happens because -;; cc-mode doesn't think it is in a buffer while loading directly -;; from the init. However, if you call it based on a file extension, -;; it works properly. Interestingly enough, this doesn't happen if -;; you don't byte-compile cc-mode. -;; -;; -;; -;; Todo: -;; -;; Get csharp-mode.el accepted as part of the emacs standard distribution. -;; Must contact monnier at iro.umontreal.ca to make this happen. -;; -;; -;; -;; Acknowledgements: -;; -;; Thanks to Alan Mackenzie and Stefan Monnier for answering questions -;; and making suggestions. -;; -;; - -;;; Versions: -;; -;; 0.1.0 - Initial release. -;; 0.2.0 - Fixed the identification on the "enum" keyword. -;; - Fixed the font-lock on the "base" keyword -;; 0.3.0 - Added a regex to fontify attributes. It isn't the -;; the best method, but it handles single-like attributes -;; well. -;; - Got "super" not to fontify as a keyword. -;; - Got extending classes and interfaces to fontify as something. -;; 0.4.0 - Removed the attribute matching because it broke more than -;; it fixed. -;; - Corrected a bug with namespace not being properly identified -;; and treating the class level as an inner object, which screwed -;; up formatting. -;; - Added "partial" to the keywords. -;; 0.5.0 - Found bugs with compiled cc-mode and loading from init files. -;; - Updated the eval-when-compile to code to let the mode be -;; compiled. -;; 0.6.0 - Added the c-filter-ops patch for 5.31.1 which made that -;; function in cc-langs.el unavailable. -;; - Added a csharp-lineup-region for indention #region and -;; #endregion block differently. -;; 0.7.0 - Added autoload so update-directory-autoloads works -;; (Thank you, Nikolaj Schumacher) -;; - Fontified the entire #region and #endregion lines. -;; - Initial work to get get, set, add, remove font-locked. -;; 0.7.1 - Added option to indent #if/endif with code -;; - Fixed c-opt-cpp-prefix defn (it must not include the BOL -;; char (^). -;; - proper fontification and indent of classes that inherit -;; (previously the colon was confusing the parser) -;; - reclassified namespace as a block beginner -;; - removed $ as a legal symbol char - not legal in C#. -;; - added struct to c-class-decl-kwds so indent is correct -;; within a struct. -;; 0.7.2 - Added automatic codedoc insertion. -;; 0.7.3 - Instance initializers (new Type { ... } ) and -;; (new Type() { ...} ) are now indented properly. -;; - proper fontification and indent of enums as brace-list-*, -;; including special treatment for enums that explicitly -;; inherit from an int type. Previously the colon was -;; confusing the parser. -;; - proper fontification of verbatim literal strings, -;; including those that end in slash. This edge case was not -;; handled at all before; it is now handled correctly. -;; - code cleanup and organization; removed the linefeed. -;; - intelligent curly-brace insertion -;; 0.7.4 - added a C# style -;; - using is now a keyword and gets fontified -;; - fixed a bug that had crept into the codedoc insertion -;; - - -(require 'cc-mode) - -(message (concat "Loading " load-file-name)) - - -;; ================================================================== -;; c# upfront stuff -;; ================================================================== - -;; This is a copy of the function in cc-mode which is used to handle -;; the eval-when-compile which is needed during other times. -(defun c-filter-ops (ops opgroup-filter op-filter &optional xlate) - ;; See cc-langs.el, a direct copy. - (unless (listp (car-safe ops)) - (setq ops (list ops))) - (cond ((eq opgroup-filter t) - (setq opgroup-filter (lambda (opgroup) t))) - ((not (functionp opgroup-filter)) - (setq opgroup-filter `(lambda (opgroup) - (memq opgroup ',opgroup-filter))))) - (cond ((eq op-filter t) - (setq op-filter (lambda (op) t))) - ((stringp op-filter) - (setq op-filter `(lambda (op) - (string-match ,op-filter op))))) - (unless xlate - (setq xlate 'identity)) - (c-with-syntax-table (c-lang-const c-mode-syntax-table) - (delete-duplicates - (mapcan (lambda (opgroup) - (when (if (symbolp (car opgroup)) - (when (funcall opgroup-filter (car opgroup)) - (setq opgroup (cdr opgroup)) - t) - t) - (mapcan (lambda (op) - (when (funcall op-filter op) - (let ((res (funcall xlate op))) - (if (listp res) res (list res))))) - opgroup))) - ops) - :test 'equal))) - - - -;; These are only required at compile time to get the sources for the -;; language constants. (The cc-fonts require and the font-lock -;; related constants could additionally be put inside an -;; (eval-after-load "font-lock" ...) but then some trickery is -;; necessary to get them compiled.) -(eval-when-compile - (let ((load-path - (if (and (boundp 'byte-compile-dest-file) - (stringp byte-compile-dest-file)) - (cons (file-name-directory byte-compile-dest-file) load-path) - load-path))) - (load "cc-mode" nil t) - (load "cc-fonts" nil t) - (load "cc-langs" nil t))) - -(eval-and-compile - ;; Make our mode known to the language constant system. Use Java - ;; mode as the fallback for the constants we don't change here. - ;; This needs to be done also at compile time since the language - ;; constants are evaluated then. - (c-add-language 'csharp-mode 'java-mode)) - -;; ================================================================== -;; end of c# upfront stuff -;; ================================================================== - - - - - -;; ================================================================== -;; csharp-mode utility and feature defuns -;; ================================================================== - -;; Indention: csharp-mode follows normal indention rules except for -;; when indenting the #region and #endregion blocks. This function -;; defines a custom indention to indent the #region blocks properly -;; - -(defun csharp-lineup-region (langelem) - "Indent all #region and #endregion blocks inline with code while -retaining normal column-zero indention for #if and the other -processing blocks. - -To use this indenting just put the following in your emacs file: - (c-set-offset 'cpp-macro 'csharp-lineup-region) - -An alternative is to use `csharp-lineup-if-and-region'. -" - - (save-excursion - (back-to-indentation) - (if (re-search-forward "#\\(end\\)?region" (c-point 'eol) [0]) 0 [0]))) - - - -(defun csharp-lineup-if-and-region (langelem) - -"Indent all #region/endregion blocks and #if/endif blocks inline -with code while retaining normal column-zero indention for any -other processing blocks. - -To use this indenting just put the following in your emacs file: - (c-set-offset 'cpp-macro 'csharp-lineup-if-and-region) - -Another option is to use `csharp-lineup-region'. - -" - (save-excursion - (back-to-indentation) - (if (re-search-forward "#\\(\\(end\\)?\\(if\\|region\\)\\|else\\)" (c-point 'eol) [0]) 0 [0]))) - - - - - -(defun csharp-insert-open-brace () - "Intelligently insert a pair of curly braces. This fn is most -often bound to the open-curly brace, with - - (local-set-key (kbd \"{\") 'csharp-insert-open-brace) - -The default binding for an open curly brace in cc-modes is often -`c-electric-brace' or `skeleton-pair-insert-maybe'. The former -can be configured to insert newlines around braces in various -syntactic positions. The latter inserts a pair of braces and -then does not insert a newline, and does not indent. - -This fn provides another option, with some additional -intelligence for csharp-mode. When you type an open curly, the -appropriate pair of braces appears, with spacing and indent set -in a context-sensitive manner. - -Within a string literal, you just get a pair of braces, and point -is set between them. Following an equals sign, you get a pair of -braces, with a semincolon appended. Otherwise, you -get the open brace on a new line, with the closing brace on the -line following. - -There may be another way to get this to happen appropriately just within emacs, -but I could not figure out how to do it. So I wrote this alternative. -" - (interactive) - (let - (tpoint - (in-string (string= (csharp-in-literal) "string")) - (preceding3 - (save-excursion - (and - (skip-chars-backward " ") - (> (- (point) 2) (point-min)) - (buffer-substring-no-properties (point) (- (point) 3))))) - (one-word-back - (save-excursion - (backward-word 2) - (thing-at-point 'word)))) - - (cond - - ;; Case 1: inside a string literal? - ;; -------------------------------------------- - ;; If so, then just insert a pair of braces and put the point - ;; between them. The most common case is a format string for - ;; String.Format() or Console.WriteLine(). - (in-string - (self-insert-command 1) - (insert "}") - (backward-char)) - - ;; Case 2: the open brace starts an array initializer. - ;; -------------------------------------------- - ;; When the last non-space was an equals sign or square brackets, - ;; then it's an initializer. - ((save-excursion - (backward-sexp) - (looking-at "\\(\\w+\\b *=\\|[[]]+\\)")) - (self-insert-command 1) - (insert " };") - (backward-char 3)) - - ;; Case 3: the open brace starts an instance initializer - ;; -------------------------------------------- - ;; If one-word-back was "new", then it's an object initializer. - ((string= one-word-back "new") - (save-excursion - (message "object initializer") - (setq tpoint (point)) ;; prepare to indent-region later - (newline) - (self-insert-command 1) - (newline-and-indent) - (newline) - (insert "};") - (c-indent-region tpoint (point)) - (previous-line) - (indent-according-to-mode) - (end-of-line) - (setq tpoint (point))) - (goto-char tpoint)) - - ;; Case 4: a lambda initialier. - ;; -------------------------------------------- - ;; If the open curly follows =>, then it's a lambda initializer. - ((string= (substring preceding3 -2) "=>") - (message "lambda init") - (self-insert-command 1) - (insert " }") - (backward-char 2)) - - ;; else, it's a new scope. (if, while, class, etc) - (t - (save-excursion - (message "new scope") - (set-mark (point)) ;; prepare to indent-region later - ;; check if the prior sexp is on the same line - (if (save-excursion - (let ((curline (line-number-at-pos)) - (aftline (progn - (backward-sexp) - (line-number-at-pos)))) - (= curline aftline))) - (newline-and-indent)) - (self-insert-command 1) - (c-indent-line-or-region) - (end-of-line) - (newline) - (insert "}") - ;;(c-indent-command) ;; not sure of the difference here - (c-indent-line-or-region) - (previous-line) - (end-of-line) - (newline-and-indent) - ;; point ends up on an empty line, within the braces, properly indented - (setq tpoint (point))) - - (goto-char tpoint))))) - - - - -;; ================================================================== -;; end of csharp-mode utility and feature defuns -;; ================================================================== - - - - - - -;; ================================================================== -;; c# values for "language constants" defined in cc-langs.el -;; ================================================================== - - -;; Java uses a series of regexes to change the font-lock for class -;; references. The problem comes in because Java uses Pascal (leading -;; space in names, SomeClass) for class and package names, but -;; Camel-casing (initial lowercase, upper case in words, -;; i.e. someVariable) for variables. The notation suggested by EMCA for C# is -;; to use Pascal notation for everything, except inner variables. So, -;; the Java regex and formatting produces very wrong results in C#. -;;(error (byte-compile-dest-file)) -;;(error (c-get-current-file)) -(c-lang-defconst c-opt-after-id-concat-key - csharp (if (c-lang-const c-opt-identifier-concat-key) - (c-lang-const c-symbol-start))) - -(c-lang-defconst c-basic-matchers-before - csharp `( - ;;;; Font-lock the attributes by searching for the - ;;;; appropriate regex and marking it as TODO. - ;;,`(,(concat "\\(" csharp-attribute-regex "\\)") - ;; 0 font-lock-function-name-face) - - ;; Put a warning face on the opener of unclosed strings that - ;; can't span lines. Later font - ;; lock packages have a `font-lock-syntactic-face-function' for - ;; this, but it doesn't give the control we want since any - ;; fontification done inside the function will be - ;; unconditionally overridden. - ,(c-make-font-lock-search-function - ;; Match a char before the string starter to make - ;; `c-skip-comments-and-strings' work correctly. - (concat ".\\(" c-string-limit-regexp "\\)") - '((c-font-lock-invalid-string))) - - ;; Fontify keyword constants. - ,@(when (c-lang-const c-constant-kwds) - (let ((re (c-make-keywords-re nil - (c-lang-const c-constant-kwds)))) - `((eval . (list ,(concat "\\<\\(" re "\\)\\>") - 1 c-constant-face-name))))) - - ;; Fontify all keywords except the primitive types. - ,`(,(concat "\\<" (c-lang-const c-regular-keywords-regexp)) - 1 font-lock-keyword-face) - - ;; Fontify leading identifiers in fully qualified names like - ;; "Foo.Bar". - ,@(when (c-lang-const c-opt-identifier-concat-key) - `((,(byte-compile - `(lambda (limit) - (while (re-search-forward - ,(concat "\\(\\<" ; 1 - "\\(" (c-lang-const c-symbol-key) - "\\)" ; 2 - "[ \t\n\r\f\v]*" - (c-lang-const - c-opt-identifier-concat-key) - "[ \t\n\r\f\v]*" - "\\)" - "\\(" - (c-lang-const - c-opt-after-id-concat-key) - "\\)") - limit t) - (unless (progn - (goto-char (match-beginning 0)) - (c-skip-comments-and-strings limit)) - (or (get-text-property (match-beginning 2) 'face) - (c-put-font-lock-face (match-beginning 2) - (match-end 2) - c-reference-face-name)) - (goto-char (match-end 1))))))))) - )) - - - -;; C# does not allow a leading qualifier operator. It also doesn't -;; allow the ".*" construct of Java. So, we redo this regex without -;; the "\\|\\*" regex. -(c-lang-defconst c-identifier-key - csharp (concat "\\(" (c-lang-const c-symbol-key) "\\)" ; 1 - (concat "\\(" - "[ \t\n\r\f\v]*" - (c-lang-const c-opt-identifier-concat-key) - "[ \t\n\r\f\v]*" - (concat "\\(" - "\\(" (c-lang-const c-symbol-key) "\\)" - "\\)") - "\\)*"))) - -;; C# has a few rules that are slightly different than Java for -;; operators. This also removed the Java's "super" and replaces it -;; with the C#'s "base". -(c-lang-defconst c-operators - csharp `((prefix "base"))) - - -;; C# uses CPP-like prefixes to mark #define, #region/endregion, -;; #if/else/endif, and #pragma. This regexp matches the prefix, -;; not including the beginning-of-line (BOL), and not including -;; the term after the prefix (define, pragma, etc). This regexp says -;; whitespace, followed by the prefix, followed by maybe more whitespace. - -(c-lang-defconst c-opt-cpp-prefix - csharp "\\s *#\\s *") - - -;; there are no message directives in C# -(c-lang-defconst c-cpp-message-directives - csharp nil) - -(c-lang-defconst c-cpp-expr-directives - csharp '("if")) - -(c-lang-defconst c-opt-cpp-macro-define - csharp "define") - -;; $ is not a legal char in an identifier in C#. So we need to -;; create a csharp-specific definition of this constant. -(c-lang-defconst c-symbol-chars - csharp (concat c-alnum "_")) - - -(c-lang-defconst c-colon-type-list-kwds - csharp '("class")) - -(c-lang-defconst c-block-prefix-disallowed-chars - - ;; Allow ':' for inherit list starters. - csharp (set-difference (c-lang-const c-block-prefix-disallowed-chars) - '(?: ?,))) - - -(c-lang-defconst c-assignment-operators - csharp '("=" "*=" "/=" "%=" "+=" "-=" ">>=" "<<=" "&=" "^=" "|=")) - -(c-lang-defconst c-primitive-type-kwds - ;; ECMA-344, S8 - csharp '("object" "string" "sbyte" "short" "int" "long" "byte" - "ushort" "uint" "ulong" "float" "double" "bool" "char" - "decimal" "void")) - -;; The keywords that define that the following is a type, such as a -;; class definition. -(c-lang-defconst c-type-prefix-kwds - ;; ECMA-344, S? - csharp '("class" "interface" "struct")) ;; no enum here. - ;; we want enum to be a brace list. - - -;; Type modifier keywords. They appear anywhere in types, but modify -;; instead of create one. -(c-lang-defconst c-type-modifier-kwds - ;; EMCA-344, S? - csharp '("readonly" "const")) - - -;; Tue, 20 Apr 2010 16:02 -;; need to vverify that this works for lambdas... -(c-lang-defconst c-special-brace-lists - csharp '((?{ . ?}) )) - - - -;; dinoch -;; Thu, 22 Apr 2010 18:54 -;; -;; No idea why this isn't getting set properly in the first place. -;; In cc-langs.el, it is set to the union of a bunch of things, none -;; of which include "new", or "enum". -;; -;; But somehow both of those show up in the resulting derived regexp. -;; This breaks indentation of instance initializers, such as -;; -;; var x = new Foo { ... }; -;; -;; Based on my inspection, the existing c-lang-defconst should work! -;; I don't know how to fix this c-lang-defconst, so I am re-setting this -;; variable here, to provide the regex explicitly. -;; -(c-lang-defconst c-decl-block-key - - csharp '"\\(namespace\\)\\([^[:alnum:]_]\\|$\\)\\|\\(class\\|interface\\|struct\\)\\([^[:alnum:]_]\\|$\\)" - ) - - - -;; Thu, 22 Apr 2010 14:29 -;; I want this to handle var x = new Foo[] { ... }; -;; not sure if necessary. -(c-lang-defconst c-inexpr-brace-list-kwds - csharp '("new")) - - -;; ;;(c-lang-defconst c-inexpr-class-kwds -;; ;; csharp '("new")) - - - -(c-lang-defconst c-class-decl-kwds - ;; EMCA-344, S? - csharp '("class" "interface" "struct" )) ;; no "enum"!! - - -;; The various modifiers used for class and method descriptions. -(c-lang-defconst c-modifier-kwds - csharp '("public" "partial" "private" "const" "abstract" - "protected" "ref" "out" "static" "virtual" - "override" "params" "internal")) - - -;; Thu, 22 Apr 2010 23:02 -;; Based on inspection of the cc-mode code, the c-protection-kwds -;; c-lang-const is used only for objective-c. So the value is -;; irrelevant for csharp. -(c-lang-defconst c-protection-kwds - csharp nil - ;; csharp '("private" "protected" "public" "internal") -) - - -;; Define the keywords that can have something following after them. -(c-lang-defconst c-type-list-kwds - csharp '("struct" "class" "interface" "is" "as" - "delegate" "event" "set" "get" "add" "remove")) - - -;; This allows the classes after the : in the class declartion to be -;; fontified. -(c-lang-defconst c-typeless-decl-kwds - csharp '(":")) - -;; Sets up the enum to handle the list properly, and also the new -;; keyword to handle object initializers. This requires a modified -;; c-basic-matchers-after (see above) in order to correctly fontify C# -;; 3.0 object initializers. -(c-lang-defconst c-brace-list-decl-kwds - csharp '("enum" "new")) - - -;; Statement keywords followed directly by a substatement. -;; catch is not one of them. -(c-lang-defconst c-block-stmt-1-kwds - csharp '("do" "try" "finally")) - - -;; Statement keywords followed by a paren sexp and then by a substatement. -(c-lang-defconst c-block-stmt-2-kwds - csharp '("for" "if" "switch" "while" "catch" "foreach" "using" - "checked" "unchecked" "lock")) - - -;; Statements that break out of braces -(c-lang-defconst c-simple-stmt-kwds - csharp '("return" "continue" "break" "throw" "goto" )) - -;; Statements that allow a label -;; TODO? -(c-lang-defconst c-before-label-kwds - csharp nil) - -;; Constant keywords -(c-lang-defconst c-constant-kwds - csharp '("true" "false" "null")) - -;; Keywords that start "primary expressions." -(c-lang-defconst c-primary-expr-kwds - csharp '("this" "base")) - -;; Treat namespace as an outer block so class indenting -;; works properly. -(c-lang-defconst c-other-block-decl-kwds - csharp '("namespace")) - -(c-lang-defconst c-other-kwds - csharp '("in" "sizeof" "typeof" "is" "as" "yield" - "where" "select" "from")) - -(c-lang-defconst c-overloadable-operators - ;; EMCA-344, S14.2.1 - csharp '("+" "-" "*" "/" "%" "&" "|" "^" - "<<" ">>" "==" "!=" ">" "<" ">=" "<=")) - - -;; This c-cpp-matchers stuff is used for fontification. -;; see cc-font.el -;; - -;; There's no preprocessor in C#, but there are still compiler -;; directives to fontify: "#pragma", #region/endregion, #define, #undef, -;; #if/else/endif. (The definitions for the extra keywords above are -;; enough to incorporate them into the fontification regexps for types -;; and keywords, so no additional font-lock patterns are required for -;; keywords.) - -(c-lang-defconst c-cpp-matchers - csharp (cons - ;; Use the eval form for `font-lock-keywords' to be able to use - ;; the `c-preprocessor-face-name' variable that maps to a - ;; suitable face depending on the (X)Emacs version. - '(eval . (list "^\\s *\\(#pragma\\|undef\\|define\\)\\>\\(.*\\)" - (list 1 c-preprocessor-face-name) - '(2 font-lock-string-face))) - ;; There are some other things in `c-cpp-matchers' besides the - ;; preprocessor support, so include it. - (c-lang-const c-cpp-matchers))) - -(defcustom csharp-font-lock-extra-types nil - "*List of extra types (aside from the type keywords) to recognize in C# mode. -Each list item should be a regexp matching a single identifier." - :type 'list :group 'csharp) - -(defconst csharp-font-lock-keywords-1 (c-lang-const c-matchers-1 csharp) - "Minimal highlighting for C# mode.") - -(defconst csharp-font-lock-keywords-2 (c-lang-const c-matchers-2 csharp) - "Fast normal highlighting for C# mode.") - -(defconst csharp-font-lock-keywords-3 (c-lang-const c-matchers-3 csharp) - "Accurate normal highlighting for C# mode.") - -(defvar csharp-font-lock-keywords csharp-font-lock-keywords-3 - "Default expressions to highlight in C# mode.") - -(defvar csharp-mode-syntax-table nil - "Syntax table used in csharp-mode buffers.") -(or csharp-mode-syntax-table - (setq csharp-mode-syntax-table - (funcall (c-lang-const c-make-mode-syntax-table csharp)))) - -(defvar csharp-mode-abbrev-table nil - "Abbreviation table used in csharp-mode buffers.") -(c-define-abbrev-table 'csharp-mode-abbrev-table - ;; Keywords that if they occur first on a line might alter the - ;; syntactic context, and which therefore should trig reindentation - ;; when they are completed. - '(("else" "else" c-electric-continued-statement 0) - ("while" "while" c-electric-continued-statement 0) - ("catch" "catch" c-electric-continued-statement 0) - ("finally" "finally" c-electric-continued-statement 0))) - -(defvar csharp-mode-map (let ((map (c-make-inherited-keymap))) - ;; Add bindings which are only useful for C# - map) - "Keymap used in csharp-mode buffers.") - - -;; TODO -;; Defines our constant for finding attributes. -;;(defconst csharp-attribute-regex "\\[\\([XmlType]+\\)(") -;;(defconst csharp-attribute-regex "\\[\\(.\\)") -;; This doesn't work because the string regex happens before this point -;; and getting the font-locking to work before and after is fairly difficult -;;(defconst csharp-attribute-regex -;; (concat -;; "\\[[a-zA-Z][ \ta-zA-Z0-9.]+" -;; "\\((.*\\)?" -;;)) - - -;; ================================================================== -;; end of c# values for "language constants" defined in cc-langs.el -;; ================================================================== - - - - -;; ================================================================== -;; C# code-doc insertion magic -;; ================================================================== -;; -;; In Visual Studio, if you type three slashes, it immediately expands into -;; an inline code-documentation fragment. The following method does the -;; same thing. -;; -;; This is the kind of thing that could be handled by YASnippet or -;; another similarly flexible snippet framework. But I don't want to -;; introduce a dependency on yasnippet to csharp-mode. So the capability -;; must live within csharp-mode itself. - -(defun csharp-maybe-insert-codedoc (arg) - - "Insert an xml code documentation template as appropriate, when -typing slashes. This fn gets bound to / (the slash key), in -csharp-mode. If the slash being inserted is not the third -consecutive slash, the slash is inserted as normal. If it is the -third consecutive slash, then a xml code documentation template -may be inserted in some cases. For example, - - a template is inserted if the prior line is empty, - or contains only an open curly brace; - a template is inserted if the prior word - closes the element; - a template is inserted if the prior word - closes the element; - an template is inserted if the prior word closes - the element; - a template is inserted if the prior word closes - a element. - -In all other cases the slash is inserted as normal. - -If you want the default cc-mode behavior, which implies no automatic -insertion of xml code documentation templates, then use this in -your `csharp-mode-hook' function: - - (local-set-key (kbd \"/\") 'c-electric-slash) - - " - (interactive "*p") - ;;(message "csharp-maybe-insert-codedoc") - (let ( - (cur-point (point)) - (char last-command-char) - (cb0 (char-before (- (point) 0))) - (cb1 (char-before (- (point) 1))) - is-first-non-whitespace - did-auto-insert - ) - - ;; check if two prior chars were slash - (if (and - (= char ?/) - cb0 (= ?/ cb0) - cb1 (= ?/ cb1) - ) - - (progn - ;;(message "yes - this is the third consecutive slash") - (setq is-first-non-whitespace - (save-excursion - (back-to-indentation) - (= cur-point (+ (point) 2)))) - - (if is-first-non-whitespace - ;; This is a 3-slash sequence. It is the first non-whitespace text - ;; on the line. Now we need to examine the surrounding context - ;; in order to determine which xml cod doc template to insert. - (let (word-back char0 char1 - word-fore char-0 char-1 - text-to-insert ;; text to insert in lieu of slash - fn-to-call ;; func to call after inserting text - (preceding-line-is-empty (or - (= (line-number-at-pos) 1) - (save-excursion - (previous-line) - (beginning-of-line) - (looking-at "[ \t]*$\\|[ \t]*{[ \t]*$")))) - (flavor 0) ;; used only for diagnostic purposes - ) - - ;;(message "starting a 3-slash comment") - ;; get the prior word, and the 2 chars preceding it. - (backward-word) - - (setq word-back (thing-at-point 'word) - char0 (char-before (- (point) 0)) - char1 (char-before (- (point) 1))) - - ;; restore prior position - (goto-char cur-point) - - ;; get the following word, and the 2 chars preceding it. - (forward-word) - (backward-word) - (setq word-fore (thing-at-point 'word) - char-0 (char-before (- (point) 0)) - char-1 (char-before (- (point) 1))) - - ;; restore prior position again - (goto-char cur-point) - - (cond - ;; The preceding line is empty, or all whitespace, or - ;; contains only an open-curly. In this case, insert a - ;; summary element pair. - (preceding-line-is-empty - (setq text-to-insert "/ \n/// \n/// " - flavor 1) ) - - ;; The preceding word closed a summary element. In this case, - ;; if the forward word does not open a remarks element, then - ;; insert a remarks element. - ((and (string-equal word-back "summary") (eq char0 ?/) (eq char1 ?<)) - (if (not (and (string-equal word-fore "remarks") (eq char-0 ?<))) - (setq text-to-insert "/ \n/// \n/// \n/// \n/// " - flavor 2))) - - ;; The preceding word closed the remarks section. In this case, - ;; insert an example element. - ((and (string-equal word-back "remarks") (eq char0 ?/) (eq char1 ?<)) - (setq text-to-insert "/ \n/// \n/// " - flavor 3)) - - ;; The preceding word closed the example section. In this - ;; case, insert an returns element. This isn't always - ;; correct, because sometimes the xml code doc is attached to - ;; a class or a property, neither of which has a return - ;; value. A more intelligent implementation would inspect the - ;; syntax state and only inject a returns element if - ;; appropriate. - ((and (string-equal word-back "example") (eq char0 ?/) (eq char1 ?<)) - (setq text-to-insert "/ " - fn-to-call (lambda () - (backward-word) - (backward-char) - (backward-char) - (c-indent-line-or-region) - ) - flavor 4)) - - ;; The preceding word opened the remarks section, or it - ;; closed a para section. In this case, insert a para - ;; element, using appropriate indentation with respect to the - ;; prior tag. - ((or - (and (string-equal word-back "remarks") (eq char0 ?<) (or (eq char1 32) (eq char1 9))) - (and (string-equal word-back "para") (eq char0 ?/) (eq char1 ?<))) - - (let (prior-point spacer) - (save-excursion - (backward-word) - (backward-char) - (backward-char) - (setq prior-point (point)) - (skip-chars-backward "\t ") - (setq spacer (buffer-substring (point) prior-point)) - ;;(message (format "pt(%d) prior(%d) spacer(%s)" (point) prior-point spacer)) - ) - - (if (string-equal word-back "remarks") - (setq spacer (concat spacer " "))) - - (setq text-to-insert (format "/%s\n///%s \n///%s" - spacer spacer spacer) - flavor 6))) - - ;; The preceding word opened a para element. In this case, if - ;; the forward word does not close the para element, then - ;; close the para element. - ;; -- - ;; This is a nice idea but flawed. Suppose I have a para element with some - ;; text in it. If I position the cursor at the first line, then type 3 slashes, - ;; I get a close-element, and that would be inappropriate. Not sure I can - ;; easily solve that problem, so the best thing might be to simply punt, and - ;; require people to close their own elements. - ;; - ;; ( (and (string-equal word-back "para") (eq char0 60) (or (eq char1 32) (eq char1 9))) - ;; (if (not (and (string-equal word-fore "para") (eq char-0 47) (eq char-1 60) )) - ;; (setq text-to-insert "/ \n/// \n///" - ;; fn-to-call (lambda () - ;; (previous-line) - ;; (end-of-line) - ;; ) - ;; flavor 7) ) - ;; ) - - ;; the default case - do nothing - (t nil)) - - (if text-to-insert - (progn - ;;(message (format "inserting special text (f(%d))" flavor)) - - ;; set the flag, that we actually inserted text - (setq did-auto-insert t) - - ;; save point of beginning of insertion - (setq cur-point (point)) - - ;; actually insert the text - (insert text-to-insert) - - ;; indent the inserted string, and re-position point, either through - ;; the case-specific fn, or via the default progn. - (if fn-to-call - (funcall fn-to-call) - - (let ((newline-count 0) (pos 0) ix) - - ;; count the number of newlines in the inserted string - (while (string-match "\n" text-to-insert pos) - (setq pos (match-end 0) - newline-count (+ newline-count 1) ) - ) - - ;; indent what we just inserted - (c-indent-region cur-point (point) t) - - ;; move up n/2 lines. This assumes that the - ;; inserted text is ~symmetric about the halfway point. - ;; The assumption holds if the xml code doc uses a - ;; begin-elt and end-elt on a new line all by themselves, - ;; and a blank line in between them where the point should be. - ;; A more intelligent implementation would use a specific - ;; marker string, like @@DOT, to note the desired point. - (previous-line (/ newline-count 2)) - (end-of-line))))))))) - - (if (not did-auto-insert) - (self-insert-command (prefix-numeric-value arg))))) - -;; ================================================================== -;; end of c# code-doc insertion magic -;; ================================================================== - - - - -;; ================================================================== -;; c# fontification extensions -;; ================================================================== -;; Commentary: -;; -;; The purpose of the following code is to fix font-lock for C#, -;; specifically for the verbatim-literal strings. C# is a cc-mode -;; language and strings are handled mostly like other c-based -;; languages. The one exception is the verbatim-literal string, which -;; uses the syntax @"...". -;; -;; `parse-partial-sexp' treats those strings as just regular strings, -;; with the @ a non-string character. This is fine, except when the -;; verblit string ends in a slash, in which case, font-lock breaks from -;; that point onward in the buffer. -;; -;; This is an attempt to fix that. -;; -;; The idea is to scan the buffer in full for verblit strings, and apply the -;; appropriate syntax-table text properties for verblit strings. Also setting -;; `parse-sexp-lookup-properties' to t tells `parse-partial-sexp' -;; to use the syntax-table text properties set up by the scan as it does -;; its parse. -;; -;; Also need to re-scan after any changes in the buffer, but on a more -;; limited region. -;; - - -;; ;; I don't remember what this is supposed to do, -;; ;; or how I figured out the value. -;; ;; -;; (defconst csharp-font-lock-syntactic-keywords -;; '(("\\(@\\)\\(\"\\)[^\"]*\\(\"\\)\\(\"\\)[^\"]*\\(\"\\)[^\"]" -;; (1 '(6)) (2 '(7)) (3 '(1)) (4 '(1)) (5 '(7)) -;; )) -;; "Highlighting of verbatim literal strings. See also the variable -;; `font-lock-keywords'.") - - - -;; Allow this: -;; (csharp-log 3 "csharp: scan...'%s'" state) - -(defvar csharp-log-level 0 - "The current log level for CSharp-specific operations. -This is used in particular by the verbatim-literal -string scanning. - -Most other csharp functions are not instrumented. -0 = NONE, 1 = Info, 2 = VERBOSE, 3 = DEBUG, 4 = SHUTUP ALREADY. ") - -(defun csharp-log (level text &rest args) - "Log a message at level LEVEL. -If LEVEL is higher than `csharp-log-level', the message is -ignored. Otherwise, it is printed using `message'. -TEXT is a format control string, and the remaining arguments ARGS -are the string substitutions (see `format')." - (if (<= level csharp-log-level) - (let* ((msg (apply 'format text args))) - (message "%s" msg) - ))) - - - -(defun csharp-max-beginning-of-stmt () - "Return the greater of `c-beginning-of-statement-1' and -`c-beginning-of-statement' . I don't understand why both of -these methods are necessary or why they differ. But they do." - - (let (dash - nodash - (curpos (point))) - - ;; I think this may need a save-excursion... - ;; Calling c-beginning-of-statement-1 resets the point! - - (setq dash (progn (c-beginning-of-statement-1) (point))) - (csharp-log 3 "C#: max-bostmt dash(%d)" dash) - (goto-char curpos) - - (setq nodash (progn (c-beginning-of-statement 1) (point))) - (csharp-log 3 "C#: max-bostmt nodash(%d)" nodash) - (goto-char curpos) - - (max dash nodash))) - - -(defun csharp-in-literal (&optional lim detect-cpp) - "Return the type of literal point is in, if any. -Basically this works like `c-in-literal' except it doesn't -use or fill the cache (`c-in-literal-cache'). - -The return value is `c' if in a C-style comment, `c++' if in a C++ -style comment, `string' if in a string literal, `pound' if DETECT-CPP -is non-nil and in a preprocessor line, or nil if somewhere else. -Optional LIM is used as the backward limit of the search. If omitted, -or nil, `c-beginning-of-syntax' is used. - -Note that this function might do hidden buffer changes. See the -comment at the start of cc-engine.el for more info." - - (let ((rtn - (save-excursion - (let* ((pos (point)) - (lim (or lim (progn - (c-beginning-of-syntax) - (point)))) - (state (parse-partial-sexp lim pos))) - (csharp-log 4 "C#: parse lim(%d) state: %s" lim (prin1-to-string state)) - (cond - ((elt state 3) - (csharp-log 4 "C#: in literal string (%d)" pos) - 'string) - ((elt state 4) - (csharp-log 4 "C#: in literal comment (%d)" pos) - (if (elt state 7) 'c++ 'c)) - ((and detect-cpp (c-beginning-of-macro lim)) 'pound) - (t nil)))))) - rtn)) - - -(defun csharp-set-vliteral-syntax-table-properties (beg end) - "Scan the buffer text between BEG and END, a verbatim literal -string, setting and clearing syntax-table text properties where -necessary. - -We need to modify the default syntax-table text property in these cases: - (backslash) - is not an escape inside a verbatim literal string. - (double-quote) - can be a literal quote, when doubled. - -BEG is the @ delimiter. END is the 'old' position of the ending quote. - -see http://www.sunsite.ualberta.ca/Documentation/Gnu/emacs-lisp-ref-21-2.7/html_node/elisp_592.html -for the list of syntax table numeric codes. - -" - - (csharp-log 3 "C#: set-vlit-syntax-table: beg(%d) end(%d)" beg end) - - (if (and (> beg 0) (> end 0)) - - (let ((curpos beg) - (state 0)) - - (c-clear-char-properties beg end 'syntax-table) - - (while (<= curpos end) - - (cond - ((= state 0) - (if (= (char-after curpos) ?@) - (progn - (c-put-char-property curpos 'syntax-table '(3)) ; (6) = expression prefix, (3) = symbol - ;;(message (format "C#: set-s-t: prefix pos(%d) chr(%c)" beg (char-after beg))) - ) - ) - (setq state (+ 1 state))) - - ((= state 1) - (if (= (char-after curpos) ?\") - (progn - (c-put-char-property curpos 'syntax-table '(7)) ; (7) = string quote - ;;(message (format "C#: set-s-t: open quote pos(%d) chr(%c)" - ;; curpos (char-after curpos))) - )) - (setq state (+ 1 state))) - - ((= state 2) - (cond - ;; handle backslash - ((= (char-after curpos) ?\\) - (c-put-char-property curpos 'syntax-table '(2)) ; (1) = punctuation, (2) = word - ;;(message (format "C#: set-s-t: backslash word pos(%d) chr(%c)" curpos (char-after curpos))) - ) - - ;; doubled double-quote - ((and - (= (char-after curpos) ?\") - (= (char-after (+ 1 curpos)) ?\")) - (c-put-char-property curpos 'syntax-table '(2)) ; (1) = punctuation, (2) = word - (c-put-char-property (+ 1 curpos) 'syntax-table '(2)) ; (1) = punctuation - ;;(message (format "C#: set-s-t: double doublequote pos(%d) chr(%c)" curpos (char-after curpos))) - (setq curpos (+ curpos 1)) - ) - - ;; a single double-quote, which should be a string terminator - ((= (char-after curpos) ?\") - (c-put-char-property curpos 'syntax-table '(7)) ; (7) = string quote - ;;(message (format "C#: set-s-t: close quote pos(%d) chr(%c)" curpos (char-after curpos))) - ;;go no further - (setq state (+ 1 state))) - - ;; everything else - (t - ;;(message (format "C#: set-s-t: none pos(%d) chr(%c)" curpos (char-after curpos))) - nil)))) - ;; next char - (setq curpos (+ curpos 1)))))) - - - -(defun csharp-end-of-verbatim-literal-string (&optional lim) - "Moves to and returns the position of the end quote of the verbatim literal -string. When calling, point should be on the @ of the verblit string. -If it is not, then no movement is performed and `point' is returned. - -This function ignores text properties. In fact it is the -underlying scanner used to set the text properties in a C# buffer. -" - - (csharp-log 3 "C#: end-of-vlit-string: point(%d) c(%c)" (point) (char-after)) - - (let (curpos - (max (or lim (point-max)))) - - (if (not (looking-at "@\"")) - (point) - (forward-char 2) ;; pass up the @ sign and first quote - (setq curpos (point)) - - ;; Within a verbatim literal string, a doubled double-quote - ;; escapes the double-quote." - (while (and ;; process characters... - (or ;; while... - (not (eq (char-after curpos) ?\")) ;; it's not a quote - (eq (char-after (+ curpos 1)) ?\")) ;; or, its a double (double) quote - (< curpos max)) ;; and we're not done yet - - (cond - ((and (eq (char-after curpos) ?\") ;; it's a double-quote. - (eq (char-after (+ curpos 1)) ?\")) - (setq curpos (+ 2 curpos))) ;; Skip 2 - (t ;; anything else - (setq curpos (+ 1 curpos))))) ;; skip fwd 1 - curpos))) - - - - -(defun csharp-scan-for-verbatim-literals-and-set-props (&optional beg end) - -"Scans the buffer, between BEG and END, for verbatim literal -strings, and sets override text properties on each string to -allow proper syntax highlighting, indenting, and cursor movement. - -BEG and END define the limits of the scan. When nil, they -default to `point-min' and `point-max' respectively. - -Setting text properties generally causes the buffer to be marked -as modified, but this fn suppresses that via the -`c-buffer-save-state' macro, for any changes in text properties -that it makes. This fn also ignores the read-only setting on a -buffer, using the same macro. - -This fn is called when a csharp-mode buffer is loaded, with BEG -and END set to nil, to do a full scan. It is also called on -every buffer change, with the BEG and END set to the values for -the change. - -The return value is nil if the buffer was not a csharp-mode -buffer. Otherwise it is the last cursor position examined by the -scan. -" - - (if (not (c-major-mode-is 'csharp-mode)) ;; don't scan if not csharp mode - nil - (save-excursion - (c-save-buffer-state - ((curpos (or beg (point-min))) - (lastpos (or end (point-max))) - (state 0) (start 0) (cycle 0) - literal eos limits) - - (csharp-log 3 "C#: scan") - (goto-char curpos) - - (while (and (< curpos lastpos) (< cycle 10000)) - (cond - - ;; Case 1: current char is a @ sign - ;; -------------------------------------------- - ;; Check to see if it demarks the beginning of a verblit - ;; string. - ((= ?@ (char-after curpos)) - - ;; are we in a comment? a string? Maybe the @ is a prefix - ;; to allow the use of a reserved word as a symbol. Let's find out. - - ;; not sure why I need both of the following. - (syntax-ppss-flush-cache 1) - (parse-partial-sexp 1 curpos) - (goto-char curpos) - (setq literal (csharp-in-literal)) - (cond - - ;; Case 1.A: it's a @ within a string. - ;; -------------------------------------------- - ;; This should never happen, because this scanner hops over strings. - ;; But it might happen if the scan starts at an odd place. - ((eq literal 'string) nil) - - ;; Case 1.B: The @ is within a comment. Hop over it. - ((and (memq literal '(c c++)) - ;; This is a kludge for XEmacs where we use - ;; `buffer-syntactic-context', which doesn't correctly - ;; recognize "\*/" to end a block comment. - ;; `parse-partial-sexp' which is used by - ;; `c-literal-limits' will however do that in most - ;; versions, which results in that we get nil from - ;; `c-literal-limits' even when `c-in-literal' claims - ;; we're inside a comment. - ;;(setq limits (c-literal-limits start))) - (setq limits (c-literal-limits))) - - ;; advance to the end of the comment - (if limits - (progn - (csharp-log 4 "C#: scan: jump end comment A (%d)" (cdr limits)) - (setq curpos (cdr limits))))) - - - ;; Case 1.B: curpos is at least 2 chars before the last - ;; position to examine, and, the following char is a - ;; double-quote (ASCII 34). - ;; -------------------------------------------- - ;; This looks like the beginning of a verbatim string - ;; literal. - ((and (< (+ 2 curpos) lastpos) - (= ?\" (char-after (+ 1 curpos)))) - - (setq eos (csharp-end-of-verbatim-literal-string)) - ;; set override syntax properties on the verblit string - (csharp-set-vliteral-syntax-table-properties curpos eos) - - (csharp-log 4 "C#: scan: jump end verblit string (%d)" eos) - (setq curpos eos)))) - - - ;; Case 2: current char is a double-quote. - ;; -------------------------------------------- - ;; If this is a string, we hop over it, on the assumption that - ;; this scanner need not bother with regular literal strings, which - ;; get the proper syntax with the generic approach. - ;; If in a comment, hop over the comment. - ((= ?\" (char-after curpos)) - (goto-char curpos) - (setq literal (c-in-literal)) - (cond - - ;; Case 2.A: a quote within a string - ;; -------------------------------------------- - ;; This shouldn't happen, because we hop over strings. - ;; But it might. - ((eq literal 'string) nil) - - ;; Case 2.B: a quote within a comment - ;; -------------------------------------------- - ((and (memq literal '(c c++)) - ;; This is a kludge for XEmacs where we use - ;; `buffer-syntactic-context', which doesn't correctly - ;; recognize "\*/" to end a block comment. - ;; `parse-partial-sexp' which is used by - ;; `c-literal-limits' will however do that in most - ;; versions, which results in that we get nil from - ;; `c-literal-limits' even when `c-in-literal' claims - ;; we're inside a comment. - ;;(setq limits (c-literal-limits start))) - (setq limits (c-literal-limits))) - - ;; advance to the end of the comment - (if limits - (progn - (setq curpos (cdr limits)) - (csharp-log 3 "C#: scan: jump end comment B (%s)" curpos)))) - - - ;; Case 2.C: Not in a comment, and not in a string. - ;; -------------------------------------------- - ;; This is the beginning of a literal (but not verbatim) string. - (t - (forward-char 1) ;; pass up the quote - (if (consp (setq limits (c-literal-limits))) - (progn - (csharp-log 4 "C#: scan: jump end literal (%d)" (cdr limits)) - (setq curpos (cdr limits)))))))) - - (setq cycle (+ 1 cycle)) - (setq curpos (+ 1 curpos)) - (c-safe (goto-char curpos))))))) - - -(defun csharp-before-font-lock (beg end old-len) - "Adjust`syntax-table' properties on the region affected by the change -in a csharp-mode buffer. - -This function is the C# value for `c-before-font-lock-function'. -It intended to be called only by the cc-mode runtime. - -It prepares the buffer for font locking, hence must get called -before `font-lock-after-change-function'. - -It does hidden buffer changes. - -BEG, END and OLD-LEN have the same meaning here as for any -after-change function. - -Point is undefined both before and after this function call. -The return value is meaningless, and is ignored by cc-mode. -" - (let ((start-scan (progn - (c-beginning-of-statement 1) - (point)))) - (csharp-scan-for-verbatim-literals-and-set-props start-scan end))) - - - -(c-lang-defconst c-before-font-lock-function - csharp 'csharp-before-font-lock) - -;; ================================================================== -;; end of c# fontification extensions -;; ================================================================== - - - - - -;; ================================================================== -;; C#-specific optimizations of cc-mode funcs -;; ================================================================== - - -;; There's never a need to check for C-style macro definitions in -;; a C# buffer. -(defadvice c-beginning-of-macro (around - csharp-mode-advice-1 - compile activate) - (if (c-major-mode-is 'csharp-mode) - nil - ad-do-it) - ) - - -;; There's never a need to move over an Obj-C directive in csharp mode -(defadvice c-forward-objc-directive (around - csharp-mode-advice-2 - compile activate) - (if (c-major-mode-is 'csharp-mode) - nil - ad-do-it) - ) - -;; ================================================================== -;; end of C#-specific optimizations of cc-mode funcs -;; ================================================================== - - - - - - - - -;; ================================================================== -;; c# - monkey-patching of basic parsing logic -;; ================================================================== -;; -;; Here, the model redefines two defuns to add special cases for csharp -;; mode. These primarily deal with indentation of instance -;; initializers, which are somewhat unique to C#. I couldn't figure out -;; how to get cc-mode to do what C# needs, without modifying these -;; defuns. -;; - -(defun c-looking-at-inexpr-block (lim containing-sexp &optional check-at-end) - ;; Return non-nil if we're looking at the beginning of a block - ;; inside an expression. The value returned is actually a cons of - ;; either 'inlambda, 'inexpr-statement or 'inexpr-class and the - ;; position of the beginning of the construct. - ;; - ;; LIM limits the backward search. CONTAINING-SEXP is the start - ;; position of the closest containing list. If it's nil, the - ;; containing paren isn't used to decide whether we're inside an - ;; expression or not. If both LIM and CONTAINING-SEXP are used, LIM - ;; needs to be farther back. - ;; - ;; If CHECK-AT-END is non-nil then extra checks at the end of the - ;; brace block might be done. It should only be used when the - ;; construct can be assumed to be complete, i.e. when the original - ;; starting position was further down than that. - ;; - ;; This function might do hidden buffer changes. - - (save-excursion - (let ((res 'maybe) passed-paren - (closest-lim (or containing-sexp lim (point-min))) - ;; Look at the character after point only as a last resort - ;; when we can't disambiguate. - (block-follows (and (eq (char-after) ?{) (point)))) - - (while (and (eq res 'maybe) - (progn (c-backward-syntactic-ws) - (> (point) closest-lim)) - (not (bobp)) - (progn (backward-char) - (looking-at "[\]\).]\\|\\w\\|\\s_")) - (c-safe (forward-char) - (goto-char (scan-sexps (point) -1)))) - - (setq res - (if (looking-at c-keywords-regexp) - (let ((kw-sym (c-keyword-sym (match-string 1)))) - (cond - ((and block-follows - (c-keyword-member kw-sym 'c-inexpr-class-kwds)) - (and (not (eq passed-paren ?\[)) - - ;; dinoch Thu, 22 Apr 2010 18:20 - ;; ============================================ - ;; looking at new MyType() { ... } - ;; means this is a brace list, so, return nil, - ;; implying NOT looking-at-inexpr-block - (not - (and (c-major-mode-is 'csharp-mode) - (looking-at "new\s+\\([[:alnum:]_]+\\)\\b"))) - - (or (not (looking-at c-class-key)) - ;; If the class instantiation is at the start of - ;; a statement, we don't consider it an - ;; in-expression class. - (let ((prev (point))) - (while (and - (= (c-backward-token-2 1 nil closest-lim) 0) - (eq (char-syntax (char-after)) ?w)) - (setq prev (point))) - (goto-char prev) - (not (c-at-statement-start-p))) - ;; Also, in Pike we treat it as an - ;; in-expression class if it's used in an - ;; object clone expression. - (save-excursion - (and check-at-end - (c-major-mode-is 'pike-mode) - (progn (goto-char block-follows) - (zerop (c-forward-token-2 1 t))) - (eq (char-after) ?\()))) - (cons 'inexpr-class (point)))) - ((c-keyword-member kw-sym 'c-inexpr-block-kwds) - (when (not passed-paren) - (cons 'inexpr-statement (point)))) - ((c-keyword-member kw-sym 'c-lambda-kwds) - (when (or (not passed-paren) - (eq passed-paren ?\()) - (cons 'inlambda (point)))) - ((c-keyword-member kw-sym 'c-block-stmt-kwds) - nil) - (t - 'maybe))) - - (if (looking-at "\\s(") - (if passed-paren - (if (and (eq passed-paren ?\[) - (eq (char-after) ?\[)) - ;; Accept several square bracket sexps for - ;; Java array initializations. - 'maybe) - (setq passed-paren (char-after)) - 'maybe) - 'maybe)))) - - (if (eq res 'maybe) - (when (and c-recognize-paren-inexpr-blocks - block-follows - containing-sexp - (eq (char-after containing-sexp) ?\()) - (goto-char containing-sexp) - (if (or (save-excursion - (c-backward-syntactic-ws lim) - (and (> (point) (or lim (point-min))) - (c-on-identifier))) - (and c-special-brace-lists - (c-looking-at-special-brace-list))) - nil - (cons 'inexpr-statement (point)))) - - res)))) - - - - -(defconst csharp-enum-decl-re - (concat - "\\\s+\\([[:alnum:]_]+\\)\s*:\s*" - "\\(" - (c-make-keywords-re nil - (list "sbyte" "byte" "short" "ushort" "int" "uint" "long" "ulong")) - "\\)") - "Regex that captures an enum declaration in C#" - ) - - - -(defun c-inside-bracelist-p (containing-sexp paren-state) - ;; return the buffer position of the beginning of the brace list - ;; statement if we're inside a brace list, otherwise return nil. - ;; CONTAINING-SEXP is the buffer pos of the innermost containing - ;; paren. PAREN-STATE is the remainder of the state of enclosing - ;; braces - ;; - ;; N.B.: This algorithm can potentially get confused by cpp macros - ;; placed in inconvenient locations. It's a trade-off we make for - ;; speed. - ;; - ;; This function might do hidden buffer changes. - (or - ;; This will pick up brace list declarations. - (c-safe - (save-excursion - (goto-char containing-sexp) - (c-forward-sexp -1) - (let (bracepos) - (if (and (or (looking-at c-brace-list-key) - - (progn (c-forward-sexp -1) - (looking-at c-brace-list-key)) - - ;; dinoch Thu, 22 Apr 2010 18:20 - ;; ============================================ - ;; looking enum Foo : int - ;; means this is a brace list, so, return nil, - ;; implying NOT looking-at-inexpr-block - - (and (c-major-mode-is 'csharp-mode) - (progn - (c-forward-sexp -1) - (looking-at csharp-enum-decl-re)))) - - (setq bracepos (c-down-list-forward (point))) - (not (c-crosses-statement-barrier-p (point) - (- bracepos 2)))) - (point))))) - ;; this will pick up array/aggregate init lists, even if they are nested. - (save-excursion - (let ((class-key - ;; Pike can have class definitions anywhere, so we must - ;; check for the class key here. - (and (c-major-mode-is 'pike-mode) - c-decl-block-key)) - bufpos braceassignp lim next-containing) - (while (and (not bufpos) - containing-sexp) - (when paren-state - (if (consp (car paren-state)) - (setq lim (cdr (car paren-state)) - paren-state (cdr paren-state)) - (setq lim (car paren-state))) - (when paren-state - (setq next-containing (car paren-state) - paren-state (cdr paren-state)))) - (goto-char containing-sexp) - (if (c-looking-at-inexpr-block next-containing next-containing) - ;; We're in an in-expression block of some kind. Do not - ;; check nesting. We deliberately set the limit to the - ;; containing sexp, so that c-looking-at-inexpr-block - ;; doesn't check for an identifier before it. - (setq containing-sexp nil) - ;; see if the open brace is preceded by = or [...] in - ;; this statement, but watch out for operator= - (setq braceassignp 'dontknow) - (c-backward-token-2 1 t lim) - ;; Checks to do only on the first sexp before the brace. - (when (and c-opt-inexpr-brace-list-key - (eq (char-after) ?\[)) - ;; In Java, an initialization brace list may follow - ;; directly after "new Foo[]", so check for a "new" - ;; earlier. - (while (eq braceassignp 'dontknow) - (setq braceassignp - (cond ((/= (c-backward-token-2 1 t lim) 0) nil) - ((looking-at c-opt-inexpr-brace-list-key) t) - ((looking-at "\\sw\\|\\s_\\|[.[]") - ;; Carry on looking if this is an - ;; identifier (may contain "." in Java) - ;; or another "[]" sexp. - 'dontknow) - (t nil))))) - ;; Checks to do on all sexps before the brace, up to the - ;; beginning of the statement. - (while (eq braceassignp 'dontknow) - (cond ((eq (char-after) ?\;) - (setq braceassignp nil)) - ((and class-key - (looking-at class-key)) - (setq braceassignp nil)) - ((eq (char-after) ?=) - ;; We've seen a =, but must check earlier tokens so - ;; that it isn't something that should be ignored. - (setq braceassignp 'maybe) - (while (and (eq braceassignp 'maybe) - (zerop (c-backward-token-2 1 t lim))) - (setq braceassignp - (cond - ;; Check for operator = - ((and c-opt-op-identifier-prefix - (looking-at c-opt-op-identifier-prefix)) - nil) - ;; Check for `= in Pike. - ((and (c-major-mode-is 'pike-mode) - (or (eq (char-after) ?`) - ;; Special case for Pikes - ;; `[]=, since '[' is not in - ;; the punctuation class. - (and (eq (char-after) ?\[) - (eq (char-before) ?`)))) - nil) - ((looking-at "\\s.") 'maybe) - ;; make sure we're not in a C++ template - ;; argument assignment - ((and - (c-major-mode-is 'c++-mode) - (save-excursion - (let ((here (point)) - (pos< (progn - (skip-chars-backward "^<>") - (point)))) - (and (eq (char-before) ?<) - (not (c-crosses-statement-barrier-p - pos< here)) - (not (c-in-literal)) - )))) - nil) - (t t)))))) - (if (and (eq braceassignp 'dontknow) - (/= (c-backward-token-2 1 t lim) 0)) - (setq braceassignp nil))) - (if (not braceassignp) - (if (eq (char-after) ?\;) - ;; Brace lists can't contain a semicolon, so we're done. - (setq containing-sexp nil) - ;; Go up one level. - (setq containing-sexp next-containing - lim nil - next-containing nil)) - ;; we've hit the beginning of the aggregate list - (c-beginning-of-statement-1 - (c-most-enclosing-brace paren-state)) - (setq bufpos (point)))) - ) - bufpos)) - )) - -;; ================================================================== -;; end of monkey-patching of basic parsing logic -;; ================================================================== - - - - -;;(easy-menu-define csharp-menu csharp-mode-map "C# Mode Commands" -;; ;; Can use `csharp' as the language for `c-mode-menu' -;; ;; since its definition covers any language. In -;; ;; this case the language is used to adapt to the -;; ;; nonexistence of a cpp pass and thus removing some -;; ;; irrelevant menu alternatives. -;; (cons "C#" (c-lang-const c-mode-menu csharp))) - -;;; Autoload mode trigger -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.cs$" . csharp-mode)) - - - -(c-add-style "C#" - '("Java" - (c-basic-offset . 4) - (c-comment-only-line-offset . (0 . 0)) - (c-offsets-alist . ( - (access-label . -) - (arglist-close . c-lineup-arglist) - (arglist-cont . 0) - (arglist-cont-nonempty . c-lineup-arglist) - (arglist-intro . c-lineup-arglist-intro-after-paren) - (block-close . 0) - (block-open . 0) - (brace-entry-open . 0) - (brace-list-close . 0) - (brace-list-entry . 0) - (brace-list-intro . +) - (brace-list-open . +) - (c . c-lineup-C-comments) - (case-label . +) - (catch-clause . 0) - (class-close . 0) - (class-open . 0) - (comment-intro . c-lineup-comment) - (cpp-macro . 0) - (cpp-macro-cont . c-lineup-dont-change) - (defun-block-intro . +) - (defun-close . 0) - (defun-open . 0) - (do-while-closure . 0) - (else-clause . 0) - (extern-lang-close . 0) - (extern-lang-open . 0) - (friend . 0) - (func-decl-cont . +) - (inclass . +) - (inexpr-class . +) - (inexpr-statement . 0) - (inextern-lang . +) - (inher-cont . c-lineup-multi-inher) - (inher-intro . +) - (inlambda . c-lineup-inexpr-block) - (inline-close . 0) - (inline-open . 0) - (innamespace . +) - (knr-argdecl . 0) - (knr-argdecl-intro . 5) - (label . 0) - (lambda-intro-cont . +) - (member-init-cont . c-lineup-multi-inher) - (member-init-intro . +) - (namespace-close . 0) - (namespace-open . 0) - (statement . 0) - (statement-block-intro . +) - (statement-case-intro . +) - (statement-case-open . +) - (statement-cont . +) - (stream-op . c-lineup-streamop) - (string . c-lineup-dont-change) - (substatement . +) - (substatement-open . 0) - (template-args-cont c-lineup-template-args +) - (topmost-intro . 0) - (topmost-intro-cont . 0) - )) - )) - - - - -;; Custom variables -;;;###autoload -(defcustom csharp-mode-hook nil - "*Hook called by `csharp-mode'." - :type 'hook - :group 'c) - - - -;;; The entry point into the mode -;;;###autoload -(defun csharp-mode () - "Major mode for editing C# code. This mode is derived from CC Mode to -support C#. - -The hook `c-mode-common-hook' is run with no args at mode -initialization, then `csharp-mode-hook'. - -This mode will automatically add a regexp for Csc.exe error and warning -messages to the `compilation-error-regexp-alist'. - -Key bindings: -\\{csharp-mode-map}" - (interactive) - (kill-all-local-variables) - (make-local-variable 'beginning-of-defun-function) - (make-local-variable 'end-of-defun-function) - (c-initialize-cc-mode t) - (set-syntax-table csharp-mode-syntax-table) - - ;; define underscore as part of a word in the Csharp syntax table - (modify-syntax-entry ?_ "w" csharp-mode-syntax-table) - - ;; define @ as an expression prefix in Csharp syntax table - (modify-syntax-entry ?@ "'" csharp-mode-syntax-table) - - (setq major-mode 'csharp-mode - mode-name "C#" - local-abbrev-table csharp-mode-abbrev-table - abbrev-mode t) - (use-local-map csharp-mode-map) - - ;; `c-init-language-vars' is a macro that is expanded at compile - ;; time to a large `setq' with all the language variables and their - ;; customized values for our language. - (c-init-language-vars csharp-mode) - - - ;; `c-common-init' initializes most of the components of a CC Mode - ;; buffer, including setup of the mode menu, font-lock, etc. - ;; There's also a lower level routine `c-basic-common-init' that - ;; only makes the necessary initialization to get the syntactic - ;; analysis and similar things working. - (c-common-init 'csharp-mode) - - - ;; csc.exe, the C# Compiler, produces errors like this: - ;; file.cs(6,18): error SC1006: Name of constructor must match name of class - - (add-hook 'compilation-mode-hook - (lambda () - (setq compilation-error-regexp-alist - (cons ' ("^[ \t]*\\([A-Za-z0-9][^(]+\\.cs\\)(\\([0-9]+\\)[,]\\([0-9]+\\)) ?: \\(error\\|warning\\) CS[0-9]+:" 1 2 3) - compilation-error-regexp-alist)))) - - ;; to allow next-error to work with csc.exe: - (setq compilation-scroll-output t) - - ;; allow fill-paragraph to work on xml code doc - (set (make-local-variable 'paragraph-separate) - "[ \t]*\\(//+\\|\\**\\)\\([ \t]+\\|[ \t]+<.+?>\\)$\\|^\f") - - - (c-run-mode-hooks 'c-mode-common-hook 'csharp-mode-hook) - - - ;; Need the following for parse-partial-sexp to work properly with - ;; verbatim literal strings Setting this var to non-nil tells - ;; `parse-partial-sexp' to pay attention to the syntax text - ;; properties on the text in the buffer. If csharp-mode attaches - ;; text syntax to @"..." then, `parse-partial-sexp' will treat those - ;; strings accordingly. - (set (make-local-variable 'parse-sexp-lookup-properties) - t) - - ;; scan the entire buffer for verblit strings - (csharp-scan-for-verbatim-literals-and-set-props nil nil) - - - (local-set-key (kbd "/") 'csharp-maybe-insert-codedoc) - (local-set-key (kbd "{") 'csharp-insert-open-brace) - - (c-update-modeline)) - - - -(message (concat "Done loading " load-file-name)) - - -(provide 'csharp-mode) - -;;; csharp-mode.el ends here -;;MD5: 4EDCB2ECE38841F407C7ED3DA8354E15 -- cgit v1.2.3-54-g00ecf