[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/csharp-mode c47e9ea 017/459: v0.8.5 - updates to imenu,
From: |
ELPA Syncer |
Subject: |
[elpa] externals/csharp-mode c47e9ea 017/459: v0.8.5 - updates to imenu, fontification |
Date: |
Sun, 22 Aug 2021 13:58:46 -0400 (EDT) |
branch: externals/csharp-mode
commit c47e9ea9a9122ae3c4aba1a4176ffd09f678a8c5
Author: Dino Chiesa <dpchiesa@hotmail.com>
Commit: Dino Chiesa <dpchiesa@hotmail.com>
v0.8.5 - updates to imenu, fontification
---
csharp-mode.el | 2868 +++++++++++++++++++++++++++++++-------------------------
1 file changed, 1606 insertions(+), 1262 deletions(-)
diff --git a/csharp-mode.el b/csharp-mode.el
index d4819fc..e91e668 100644
--- a/csharp-mode.el
+++ b/csharp-mode.el
@@ -4,10 +4,10 @@
;; Maintainer : Dino Chiesa <dpchiesa@hotmail.com>
;; Created : Feburary 2005
;; Modified : May 2011
-;; Version : 0.8.4
+;; Version : 0.8.5
;; Keywords : c# languages oop mode
;; X-URL : http://code.google.com/p/csharpmode/
-;; Last-saved : <2011-May-19 11:42:29>
+;; Last-saved : <2011-May-21 20:26:02>
;;
;; This program is free software; you can redistribute it and/or modify
@@ -65,8 +65,9 @@
;; - yasnippet integration
;; - preloaded snippets
;;
-;; - imenu integration - generates an index of namespaces/classes/methods
-;; for easy navigation within the buffer.
+;; - imenu integration - generates an index of namespaces, classes,
+;; interfaces, methods, and properties for easy navigation within
+;; the buffer.
;;
@@ -219,8 +220,18 @@
;;; Known Bugs:
;;
+;; The imenu scan is text-based and naive. For example, if you
+;; intersperse comments between the name of a class/method/namespace,
+;; and the curly brace, the scan will not recognize the thing being
+;; declared. This is fixable - would need to extract the buffer
+;; substring then remove comments before doing the regexp checks - but
+;; it would make the scan much slower. Also, the scan doesn't deal
+;; with preproc symbol definitions and #if/#else. Those things are
+;; invisible to the scanner csharp-mode uses to build the imenu menu.
+;;
;; Leading identifiers are no longer being fontified, for some reason.
-;; See matchers-before.
+;; See matchers-before. (Not sure this is still a problem - 19 may
+;; 2011 DPC)
;;
;; Method names with a preceding attribute are not fontified.
;;
@@ -239,9 +250,19 @@
;;
;; Todo:
;;
+;; imenu should scan for and find delegates and events, in addition
+;; to the classes, structs, properties and methods it does currently.
+;;
;; Get csharp-mode.el accepted as part of the emacs standard distribution.
;; Must contact monnier at iro.umontreal.ca to make this happen.
;;
+;; Add refactoring capabilities?
+;; - extract as method - extract a block of code into a method
+;; - extract as Func<> - extract a block of code into an Action<T>
+;;
+;; More code-gen power:
+;; - interface implementation - I think would require csharp-shell
+;;
;;
;; Acknowledgements:
;;
@@ -297,8 +318,9 @@
;; - 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
+;; - code cleanup and organization; removed the formfeed.
+;; - intelligent curly-brace insertion with
+;; `csharp-insert-open-brace'
;; 0.7.4 - added a C# style
;; - using is now a keyword and gets fontified correctly
;; - fixed a bug that had crept into the codedoc insertion.
@@ -325,11 +347,11 @@
;; 0.8.0 - include flymake magic into this module.
;; - include yasnippet integration
;;
-;; 0.8.2 April 2011 DPC
+;; 0.8.2 2011 April DPC
;; - small tweaks; now set a one-time bool for flymake installation
;; - some doc updates on flymake
;;
-;; 0.8.3 May 17 2001 DPC
+;; 0.8.3 2011 May 17 DPC
;; - better help on csharp-mode
;; - csharp-move-* functions for manual navigation.
;; - imenu integration for menu-driven navigation - navigate to
@@ -340,11 +362,22 @@
;; 0.8.4 DPC 2011 May 18
;; - fix a basic bug in the `csharp-yasnippet-fixup' fn.
;;
-
-
+;; 0.8.5 DPC 2011 May 21
+;; - imenu: correctly parse Properties that are part of an
+;; explicitly specified interface. Probably need to do this
+;; for methods, too.
+;; - fontify the optional alias before namespace in a using (import).
+;; - Tweak open-curly magic insertion for object initializers.
+;; - better fontification of variables and references
+;; - "sealed" is now fontified as a keyword
+;; - imenu: correctly index ctors that call this or base.
+;; - imenu: correctly index Extension methods (this System.Enum e)
+;; - imenu: correctly scan method params tagged with out, ref, params
+;; - imenu scan: now handle curlies within strings.
+;; - imenu: split menus now have better labels, are sorted correctly.
+;;
(require 'cc-mode)
-;;(require 'cl)
(message (concat "Loading " load-file-name))
@@ -394,7 +427,7 @@
;; These are only required at compile time to get the sources for the
-;; language constants. (The cc-fonts require and the font-lock
+;; language constants. (The load of cc-fonts 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.)
@@ -435,6 +468,7 @@
"<%@.+?%>"
"Regex for matching directive blocks in ASP.NET files (.aspx, .ashx, .ascx)")
+
(defconst csharp-enum-decl-re
(concat
"\\<enum[ \t\n\r\f\v]+"
@@ -462,14 +496,25 @@
(defun csharp--at-vsemi-p (&optional pos)
"Determines if there is a virtual semicolon at POS or point.
-This is the C# version of the function.
+It returns t if at a position where a virtual-semicolon is.
+Otherwise nil.
+
+This is the C# version of the function. It gets set into
+the variable `c-at-vsemi-p-fn'.
-A vsemi is a cc-mode concept implying end-of-statement, without
-a semicolon or close-brace. This happens in 2 cases in C#:
+A vsemi is a cc-mode concept implying the end of a statement,
+where no actual end-of-statement signifier character ( semicolon,
+close-brace) appears. The concept is used to allow proper
+indenting of blocks of code: Where a vsemi appears, the following
+line will not indent further.
+
+A vsemi appears in 3 cases in C#:
- after an attribute that decorates a class, method, field, or
property.
+ - in an object initializer, before the open-curly?
+
- after an ASPNET directive, that appears in a aspx/ashx/ascx file
An example of the former is [WebMethod] or [XmlElement].
@@ -481,14 +526,20 @@ Providing this function allows the indenting in
csharp-mode
to work properly with code that includes attributes and ASPNET
directives.
-Returns t if at a position where a virtual-semicolon is.
-Otherwise nil.
"
(save-excursion
(let ((pos-or-point (progn (if pos (goto-char pos)) (point))))
(cond
+ ;; before open curly in object initializer. new Foo* { }
+ ((and (looking-back
+ (concat "\\<new[ \t\n\f\v\r]+"
+ "\\(?:[A-Za-z_][[:alnum:]]*\\.\\)*"
+ "[A-Za-z_][[:alnum:]]*[\ t\n\f\v\r]*"))
+ (looking-at "[ \t\n\f\v\r]*{"))
+ t)
+
;; put a vsemi after an ASPNET directive, like
;; <%@ WebHandler Language="C#" Class="Handler" %>
((looking-back (concat csharp-aspnet-directive-re "$") nil t)
@@ -496,6 +547,8 @@ Otherwise nil.
;; put a vsemi after an attribute, as with
;; [XmlElement]
+ ;; Except when the attribute is used within a line of code, as
+ ;; specifying something for a parameter.
((c-safe (backward-sexp) t)
(cond
((re-search-forward
@@ -514,8 +567,8 @@ Otherwise nil.
(c-backward-syntactic-ws)
(cond
- ((eq (char-before) 93) ;; close sq brace
- (csharp--at-vsemi-p (point)))
+ ((eq (char-before) 93) ;; close sq brace (a previous attribute)
+ (csharp--at-vsemi-p (point))) ;; recurse
((or
(eq (char-before) 59) ;; semicolon
@@ -523,6 +576,7 @@ Otherwise nil.
(eq (char-before) 125)) ;; close curly
t)
+ ;; attr is used within a line of code
(t nil)))
(t nil)))
@@ -550,6 +604,8 @@ An alternative is to use `csharp-lineup-if-and-region'.
+
+
(defun csharp-lineup-if-and-region (langelem)
"Indent all #region/endregion blocks and #if/endif blocks inline
@@ -604,33 +660,51 @@ comment at the start of cc-engine.el for more info."
rtn))
+
(defun csharp-insert-open-brace ()
- "Intelligently insert a pair of curly braces. This fn is most
- often bound to the open-curly brace, with
+ "Intelligently insert a pair of curly braces. This fn should be
+bound to the open-curly brace, with
- (local-set-key (kbd \"{\") 'csharp-insert-open-brace)
+ (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.
+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.
+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, followed by an empty line
- and the closing brace on the line following, with point on
- the empty line.
+ - Within a string literal, you just get a pair of braces, and
+ point is set between them. This works for String.Format()
+ purposes.
- 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.
+ - Following = or [], as in an array assignment, you get a pair
+ of braces, with two intervening spaces, with a semincolon
+ appended. Point is left between the braces.
+
+ - Following \"new Foo\", it's an object initializer. You get:
+ newline, open brace, newline, newline, close, semi. Point is
+ left on the blank line between the braces. Unless the object
+ initializer is within an array initializer, in which case, no
+ newlines, and the semi is replaced with a comma. (Try it to
+ see what this means).
+
+ - Following => , implying a lambda, you get an open/close pair,
+ with two intervening spaces, no semicolon, and point on the
+ 2nd space.
+
+ - Otherwise, you get a newline, the open curly, followed by
+ an empty line and the closing curly on the line following,
+ with point on the empty line.
+
+
+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)
@@ -675,26 +749,40 @@ comment at the start of cc-engine.el for more info."
;; --------------------------------------------
;; 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))
- (forward-line -1)
- (indent-according-to-mode)
- (end-of-line)
- (setq tpoint (point)))
- (goto-char tpoint))
+ (csharp-log 2 "object initializer")
+ (setq tpoint (point)) ;; prepare to indent-region later
+ (backward-word 2)
+ (c-backward-syntactic-ws)
+ (if (or (eq (char-before) ?,) ;; comma
+ (and (eq (char-before) 123) ;; open curly
+ (progn (backward-char)
+ (c-backward-syntactic-ws)
+ (looking-back "\\[\\]"))))
+ (progn
+ ;; within an array - emit no newlines
+ (goto-char tpoint)
+ (self-insert-command 1)
+ (insert " },")
+ (backward-char 3))
+
+ (progn
+ (goto-char tpoint)
+ (newline)
+ (self-insert-command 1)
+ (newline-and-indent)
+ (newline)
+ (insert "};")
+ (c-indent-region tpoint (point))
+ (forward-line -1)
+ (indent-according-to-mode)
+ (end-of-line))))
+
;; Case 4: a lambda initialier.
;; --------------------------------------------
;; If the open curly follows =>, then it's a lambda initializer.
((string= (substring preceding3 -2) "=>")
- (message "lambda init")
+ (csharp-log 2 "lambda init")
(self-insert-command 1)
(insert " }")
(backward-char 2))
@@ -702,7 +790,7 @@ comment at the start of cc-engine.el for more info."
;; else, it's a new scope. (if, while, class, etc)
(t
(save-excursion
- (message "new scope")
+ (csharp-log 2 "new scope")
(set-mark (point)) ;; prepare to indent-region later
;; check if the prior sexp is on the same line
(if (save-excursion
@@ -749,9 +837,14 @@ comment at the start of cc-engine.el for more info."
;; This const is now internal (obsolete); need to move to
;; c-after-id-concat-ops. I don't yet understand the meaning
;; of that variable, so for now. . . .
+
+;; (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-opt-after-id-concat-key
- csharp (if (c-lang-const c-opt-identifier-concat-key)
- (c-lang-const c-symbol-start)))
+ csharp "[[:alpha:]_]" )
+
@@ -767,20 +860,22 @@ comment at the start of cc-engine.el for more info."
;;
;; (c-make-font-lock-search-function regexp '(A B c))
;;
-;; The REGEXP is used in re-search-forward, and if there's a match, the
-;; A B and C are three forms that are called in a weird combination.
+;; The REGEXP is used in re-search-forward, and if there's a match, then
+;; A is called within a save-match-data. If B and C are non-nil, they
+;; are called as pre and post blocks, respecitvely.
;;
;; Anyway the c-make-font-lock-search-function works for a single regex,
;; but more complicated scenarios such as those intended to match and
;; fontify object initializers, call for a hand-crafted lambda.
;;
-;; The object initializer is special because, matching on it must
+;; The object initializer is special because matching on it must
;; allow nesting.
;;
;; In c#, the object initializer block is used directly after a
;; constructor, like this:
;;
-;; new MyType {
+;; new MyType
+;; {
;; Prop1 = "foo"
;; }
;;
@@ -933,9 +1028,18 @@ comment at the start of cc-engine.el for more info."
;; Fontify the namespaces that follow using statements.
- ;; This regex handles the optional alias, but does not fontify it.
-
,`("\\<\\(using\\)\s+\\(?:[A-Za-z_][[:alnum:]]*\s*=\s*\\)?\\(\\(?:[A-Za-z_][[:alnum:]]*\\.\\)*[A-Za-z_][[:alnum:]]*\\)\s*;"
- 2 font-lock-constant-face)
+ ;; This regex handles the optional alias, as well.
+ ,`(,(concat
+ "\\<\\(using\\)[ \t\n\f\v\r]+"
+ "\\(?:"
+ "\\([A-Za-z_][[:alnum:]]*\\)"
+ "[ \t\n\f\v\r]*="
+ "[ \t\n\f\v\r]*"
+ "\\)?"
+ "\\(\\(?:[A-Za-z_][[:alnum:]]*\\.\\)*[A-Za-z_][[:alnum:]]*\\)"
+ "[ \t\n\f\v\r]*;")
+ (2 font-lock-constant-face t t)
+ (3 font-lock-constant-face))
;; Fontify all keywords except the primitive types.
@@ -943,33 +1047,82 @@ comment at the start of cc-engine.el for more info."
1 font-lock-keyword-face)
- ;; Fontify leading identifiers in fully qualified names like
- ;; "Foo.Bar".
+ ;; Fontify leading identifiers as a reference? in fully
+ ;; qualified names like "Foo.Bar".
,@(when (c-lang-const c-opt-identifier-concat-key)
`((,(byte-compile
`(lambda (limit)
+ (csharp-log 3 "bmb reference? p(%d) L(%d)" (point)
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]+"
+ ,(concat "\\(\\<" ;; 1
+ "\\(" ;; 2
+ ;;"[A-Z]";; uppercase - assume upper =
classname
+ "[A-Za-z_]" ;; any old
+ "[A-Za-z0-9_]*" ;; old: (c-lang-const
c-symbol-key)
"\\)"
+ "[ \t\n\r\f\v]*"
+ "\\." ;;(c-lang-const
c-opt-identifier-concat-key)
+ "[ \t\n\r\f\v]*"
+ "\\)" ;; 1 ends
"\\("
- (c-lang-const
- c-opt-after-id-concat-key)
- "\\)")
+ "[[:alpha:]_][A-Za-z0-9_]*" ;; start
of another symbolname
+ "\\)" ;; 3 ends
+ )
limit t)
+ (csharp-log 3 "bmb ref? B(%d)" (match-beginning 0))
(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)))))))))
+ (let* ((prefix (match-string 2))
+ (me1 (match-end 1))
+ (first-char (string-to-char prefix))
+ (is-upper (and (>= first-char 65)
+ (<= first-char 90))))
+ (csharp-log 3 " - class/intf ref (%s)" prefix)
+ ;; only put face if not there already
+ (or (get-text-property (match-beginning 2) 'face)
+ (c-put-font-lock-face (match-beginning 2)
+ (match-end 2)
+ (if is-upper
+ font-lock-type-face
;; it's a type!
+
font-lock-variable-name-face)))
+
+ (goto-char (match-end 3))
+ (c-forward-syntactic-ws limit)
+
+ ;; now, maybe fontify the thing afterwards, too
+ (let ((c (char-after)))
+ (csharp-log 3 " - now lkg at c(%c)" c)
+
+ (cond
+
+ ((= c 40) ;; open paren
+ (or (get-text-property (match-beginning 3)
'face)
+ (c-put-font-lock-face (match-beginning 3)
+ (match-end 3)
+
font-lock-function-name-face))
+ (goto-char (match-end 3)))
+
+ ;; these all look like variables or properties
+ ((or (= c 59) ;; semicolon
+ (= c 91) ;; open sq brack
+ (= c 41) ;; close paren
+ (= c 44) ;; ,
+ (= c 33) ;; !
+ (= c 124) ;; |
+ (= c 61) ;; =
+ (= c 43) ;; +
+ (= c 45) ;; -
+ (= c 42) ;; *
+ (= c 47)) ;; /
+ (or (get-text-property (match-beginning 3)
'face)
+ (c-put-font-lock-face (match-beginning 3)
+ (match-end 3)
+
font-lock-variable-name-face))
+ (goto-char (match-end 3)))
+
+ (t
+ (goto-char (match-end 1)))))))))))))
))
@@ -1019,7 +1172,6 @@ comment at the start of cc-engine.el for more info."
;; Prop1= new Bar { PropA = 5.6F }
;; };
;;
-
,@(when t
`((,(byte-compile
`(lambda (limit)
@@ -1042,7 +1194,7 @@ comment at the start of cc-engine.el for more info."
(goto-char (match-beginning 0))
(c-skip-comments-and-strings limit))
- (csharp-log 3 "ctor candidate at %d"
(match-beginning 1))
+ (csharp-log 3 "ctor invoke? at %d"
(match-beginning 1))
(save-match-data
;; next thing could be: [] () <> or {} or
nothing (semicolon, comma).
@@ -1053,10 +1205,10 @@ comment at the start of cc-engine.el for more info."
'font-lock-type-face)
(goto-char (match-end 0))
- (c-forward-syntactic-ws)
+ (c-forward-syntactic-ws limit)
(if (eq (char-after) ?<) ;; ctor for generic
type
(progn
- (csharp-log 3 " - generic ctor")
+ (csharp-log 3 " - this is a generic
type")
;; skip over <> safely
(c-safe (c-forward-sexp 1) t)
(c-forward-syntactic-ws)))
@@ -1075,7 +1227,8 @@ comment at the start of cc-engine.el for more info."
(c-safe (c-forward-sexp 1) t)))
(progn
- ;; at this point we've jumped over any
intervening s-exp
+ ;; at this point we've jumped over any
intervening s-exp,
+ ;; like sq brackets or parens.
(c-forward-syntactic-ws)
(csharp-log 3 " - after fwd-syn-ws
point(%d)" (point))
(csharp-log 3 " - next char: %c"
(char-after))
@@ -1083,7 +1236,7 @@ comment at the start of cc-engine.el for more info."
(let ((start (point))
(end (if (c-safe
(c-forward-sexp 1) t)
(point) 0)))
- (csharp-log 3 " - put
c-decl-id-start on the open-curly at %d" start)
+ (csharp-log 3 " - open curly gets
c-decl-id-start %d" start)
(c-put-char-property start
'c-type
'c-decl-id-start)
@@ -1098,7 +1251,7 @@ comment at the start of cc-engine.el for more info."
(csharp-log 3 " - next
char: %c" (char-after))
;; fontify each property
assignment
(if (re-search-forward
- (concat "\\("
(c-lang-const c-symbol-key) "\\)\s*=")
+ (concat "\\("
(c-lang-const c-symbol-key) "\\)\\s*=")
end t)
(progn
(csharp-log 3 " -
found variable %d-%d"
@@ -1150,7 +1303,7 @@ comment at the start of cc-engine.el for more info."
"{")
limit t)
- (csharp-log 3 "enum candidate at %d"
(match-beginning 0))
+ (csharp-log 3 "enum? at %d" (match-beginning 0))
(unless
(progn
@@ -1195,6 +1348,7 @@ comment at the start of cc-engine.el for more info."
"("
"\\)")
limit t)
+
(unless
(progn
(goto-char (match-beginning 0))
@@ -1202,7 +1356,8 @@ comment at the start of cc-engine.el for more info."
(goto-char (match-end 0))
- (csharp-log 3 "ctor decl candidate ending at %d"
(point))
+ (csharp-log 3 "ctor decl? L(%d) B(%d) E(%d)"
+ limit (match-beginning 0) (point))
(backward-char 1) ;; just left of the open paren
(save-match-data
@@ -1237,7 +1392,7 @@ comment at the start of cc-engine.el for more info."
;; open curly. no depedency on other
ctor.
((eq (char-after) ?{)
- (csharp-log 3 " - ctor with no
dependency? at %d" (point))
+ (csharp-log 3 " - no dependency, curly
at %d" (point))
(setq found-it t)))
)))
@@ -1264,7 +1419,7 @@ comment at the start of cc-engine.el for more info."
"(")
limit t)
- (csharp-log 3 "using clause at %d" (match-beginning
0))
+ (csharp-log 3 "using clause p(%d)" (match-beginning
0))
(unless
(progn
@@ -1326,8 +1481,9 @@ comment at the start of cc-engine.el for more info."
(if is-attr
(progn
- (csharp-log 3 " - attribute seems likely. type:
%d - %d"
- b2 e2)
+ (if (<= 3 csharp-log-level)
+ (csharp-log 3 " - attribute: '%s'"
+ (buffer-substring-no-properties
b2 e2)))
(c-put-font-lock-face b2 e2
'font-lock-type-face)))))
(goto-char (match-end 0))
))
@@ -1483,6 +1639,7 @@ comment at the start of cc-engine.el for more info."
))
+
;; C# does generics. Setting this to t tells the parser to put
;; parenthesis syntax on angle braces that surround a comma-separated
;; list.
@@ -1490,7 +1647,6 @@ comment at the start of cc-engine.el for more info."
csharp t)
-
(c-lang-defconst c-identifier-key
csharp (concat "\\([[:alpha:]_][[:alnum:]_]*\\)" ; 1
"\\("
@@ -1508,10 +1664,11 @@ comment at the start of cc-engine.el for more info."
;; 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.
+;; #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, region, etc). This regexp says
+;; whitespace, followed by the prefix, followed by maybe more
+;; whitespace.
(c-lang-defconst c-opt-cpp-prefix
csharp "\\s *#\\s *")
@@ -1532,6 +1689,13 @@ comment at the start of cc-engine.el for more info."
(c-lang-defconst c-symbol-chars
csharp (concat c-alnum "_"))
+;; c-identifier-syntax-modifications by default defines $ as a word
+;; syntax, which is not legal in C#. So, define our own lang-specific
+;; value.
+(c-lang-defconst c-identifier-syntax-modifications
+ csharp '((?_ . "w")))
+
+
(c-lang-defconst c-colon-type-list-kwds
csharp '("class"))
@@ -1608,12 +1772,15 @@ comment at the start of cc-engine.el for more info."
(c-lang-defconst c-class-decl-kwds
;; EMCA-344, S?
+ ;; don't include enum here, because we want it to be fontified as a brace
+ ;; list, with commas delimiting the values. see c-brace-list-decl-kwds
+ ;; below.
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"
+ csharp '("public" "partial" "private" "const" "abstract" "sealed"
"protected" "ref" "out" "static" "virtual"
"override" "params" "internal"))
@@ -1648,9 +1815,9 @@ comment at the start of cc-engine.el for more info."
;; Statement keywords followed directly by a substatement.
-;; catch is not one of them.
+;; catch is not one of them, because catch has a paren (typically).
(c-lang-defconst c-block-stmt-1-kwds
- csharp '("do" "try" "finally"))
+ csharp '("do" "try" "finally" "unsafe"))
;; Statement keywords followed by a paren sexp and then by a substatement.
@@ -1682,8 +1849,8 @@ comment at the start of cc-engine.el for more info."
csharp '("namespace"))
(c-lang-defconst c-other-kwds
- csharp '("in" "sizeof" "typeof" "is" "as" "yield"
- "where" "select" "from"))
+ csharp '("sizeof" "typeof" "is" "as" "yield"
+ "where" "select" "in" "from"))
(c-lang-defconst c-overloadable-operators
;; EMCA-344, S14.2.1
@@ -2136,7 +2303,7 @@ Some notes on implementation:
compiles *that*. This temporary file has a different name
than the actual file name for the buffer - _flymake gets
appended to the basename. Therefore, you should specify
- xxx_flymake.cs for the filename, if you want to explicitly
+ Foo_flymake.cs for the filename, if you want to explicitly
refer to it.
If you want to refer to it implicitly, you can use the special
@@ -2255,7 +2422,6 @@ Some notes on implementation:
(defun csharp-flymake-install ()
-
"Change flymake variables and fns to work with C#.
This fn does these things:
@@ -2524,6 +2690,7 @@ This fn does these things:
"static\\|"
"\\)"
"[ \t\n\r\f\v]+"
+ "\\(?:override[ \t\n\r\f\v]+\\)?" ;; optional
"\\([[:alpha:]_][^\t\(\n]+\\)" ;; 2. return type -
possibly generic
"[ \t\n\r\f\v]+"
"\\([[:alpha:]_][[:alnum:]_]*\\)" ;; 3. name of func
@@ -2545,14 +2712,20 @@ This fn does these things:
"\\([[:alpha:]_][[:alnum:]_]*\\)" ;; 2. name of ctor
"[ \t\n\r\f\v]*"
"\\(\([^\)]*\)\\)" ;; 3. parameter list
(with parens)
+ "\\(" ;; 4. ctor dependency
+ "[ \t\n]*:[ \t\n]*" ;; colon
+ "\\(?:this\\|base\\)" ;; this or base
+ "[ \t\n\r\f\v]*"
+ "\\(?:\([^\)]*\)\\)" ;; parameter list (with
parens)
+ "\\)?" ;; possibly
"[ \t\n\r\f\v]*"
))
`(using-stmt
,(concat
- "^[ \t\n\r\f\v]*"
- "\\(using\\)"
+ ;;"^[ \t\n\r\f\v]*"
+ "\\(\\<using\\)"
"[ \t\n\r\f\v]+"
"\\(?:"
"\\([[:alpha:]_][[:alnum:]_]*\\)" ;; alias
@@ -2572,25 +2745,47 @@ This fn does these things:
,(concat
"^[ \t]*" ;; leading whitespace
"\\("
- "public\\(?: static\\)?\\|"
- "internal\\(?: static\\)?\\|"
- "static\\(?: internal\\)?\\|"
- "internal\\(?: sealed\\)?\\|"
- "sealed\\(?: internal\\)?\\|"
- "static\\|"
- "sealed\\|"
+ "public\\(?: \\(?:static\\|sealed\\)\\)?[ \t]+\\|" ;; access
modifiers
+ "internal\\(?: \\(?:static\\|sealed\\)\\)?[ \t]+\\|"
+ "static\\(?: internal\\)?[ \t]+\\|"
+ "sealed\\(?: internal\\)?[ \t]+\\|"
+ "static[ \t]+\\|"
+ "sealed[ \t]+\\|"
"\\)"
- "[ \t]+"
"\\(\\(?:partial[ \t]+\\)?class\\|struct\\)" ;; class/struct keyword
"[ \t]+"
"\\([[:alpha:]_][[:alnum:]]*\\)" ;; type name
"\\("
"[ \t\n]*:[ \t\n]*" ;; colon
+ "\\([[:alpha:]_][^\t\(\n]+\\)" ;; base / intf - poss
generic
+ "\\("
+ "[ \t\n]*,[ \t\n]*"
+ "\\([[:alpha:]_][^\t\(\n]+\\)" ;; addl interface - poss
generic
+ "\\)*"
+ "\\)?" ;; possibly
+ "[ \t\n\r\f\v]*"
+ ))
+
+ `(genclass-start
+ ,(concat
+ "^[ \t]*" ;; leading whitespace
"\\("
- "\\([[:alpha:]_][^\t\(\n]+\\)" ;; parent type or intf -
poss generic
+ "public\\(?: \\(?:static\\|sealed\\)\\)?[ \t]+\\|" ;; access
modifiers
+ "internal\\(?: \\(?:static\\|sealed\\)\\)?[ \t]+\\|"
+ "static\\(?: internal\\)?[ \t]+\\|"
+ "sealed\\(?: internal\\)?[ \t]+\\|"
+ "static[ \t]+\\|"
+ "sealed[ \t]+\\|"
"\\)"
- "\\([ \t\n]*,[ \t\n]*"
- "\\([[:alpha:]_][^\t\(\n]+\\)" ;; addl interface -
possibly generic
+ "\\(\\(?:partial[ \t]+\\)?class\\|struct\\)" ;; class/struct keyword
+ "[ \t]+"
+ "\\([[:alpha:]_][[:alnum:]_<>, ]*\\)" ;; type name (generic)
+ "\\("
+ "[ \t\n]*:[ \t\n]*" ;; colon
+ "\\([[:alpha:]_][^\t\(\n]+\\)" ;; base / intf - poss
generic
+ "\\("
+ "[ \t\n]*,[ \t\n]*"
+ "\\([[:alpha:]_][^\t\(\n]+\\)" ;; addl interface - poss
generic
"\\)*"
"\\)?" ;; possibly
"[ \t\n\r\f\v]*"
@@ -2642,7 +2837,10 @@ This fn does these things:
"[ \t\n\r\f\v]+"
"\\([[:alpha:]_][^\t\(\n]+\\)" ;; 2: return type -
possibly generic
"[ \t\n\r\f\v]+"
- "\\([[:alpha:]_][[:alnum:]_]*\\)" ;; 3: name of prop
+ "\\("
+ "\\(?:[A-Za-z_][[:alnum:]_]*\\.\\)*" ;; possible prefix
interface
+ "[[:alpha:]_][[:alnum:]_]*" ;; 3: name of prop
+ "\\)"
"[ \t\n\r\f\v]*"
))
@@ -2676,7 +2874,7 @@ This fn does these things:
"\\(namespace\\)"
"[ \t\n\r\f\v]+"
"\\("
- "\\(?:[A-Za-z_][[:alnum:]]*\\.\\)*" ;; name of namespace
+ "\\(?:[A-Za-z_][[:alnum:]_]*\\.\\)*" ;; name of namespace
"[A-Za-z_][[:alnum:]]*"
"\\)"
"[ \t\n\r\f\v]*"
@@ -2822,6 +3020,11 @@ See also, `csharp-move-fwd-to-end-of-defun'.
(not (looking-back (csharp--regexp 'namespace-start)))
(looking-back (csharp--regexp 'class-start))))
+(defun csharp--on-genclass-open-curly-p ()
+ "return t when point is on the open-curly of a generic class."
+ (and (looking-at "{")
+ (looking-back (csharp--regexp 'genclass-start))))
+
(defun csharp--on-namespace-open-curly-p ()
"return t when point is on the open-curly of a namespace."
(and (looking-at "{")
@@ -2848,8 +3051,6 @@ See also, `csharp-move-fwd-to-end-of-defun'.
(and (looking-at "{")
(looking-back (csharp--regexp 'indexer-start))))
-;;(not (string= (match-string-no-properties 2) "class"))))
-
(defun csharp--on-enum-open-curly-p ()
"return t when point is on the open-curly of a interface."
(and (looking-at "{")
@@ -3091,107 +3292,194 @@ This fn returns a string of the form TYPE1 [,
TYPE2...]
Upon entry, it's assumed that the parens included in S.
"
+ (if (string= s "()")
+ s
+ (save-match-data
+ (let* (new
+ (state 0) ;; 0 => ws, 1=>slurping param...
+ c
+ cs
+ nesting
+ need-type
+ ix2
+ (s2 (substring s 1 -1))
+ (len (length s2))
+ (i (1- len)))
+
+ (while (> i 0)
+ (setq c (aref s2 i) ;; current character
+ cs (char-to-string c)) ;; s.t. as a string
- (let* (new
- (state 0) ;; 0 => ws, 1=>slurping param...
- i
- c
- cs
- nesting
- need-type
- ix2
- (s2 (substring s 1 -1))
- (len (length s2))
- (i (1- len)))
+ (cond
- (while (> i 0)
- (setq c (aref s2 i) ;; current character
- cs (char-to-string c)) ;; s.t. as a string
+ ;; backing over whitespace "after" the param
+ ((= state 0)
+ (cond
+ ;; more ws
+ ((string-match "[ \t\f\v\n\r]" cs)
+ t)
+ ;; a legal char for an identifier
+ ((string-match "[A-Za-z_0-9]" cs)
+ (setq state 1))
+ (t
+ (error "unexpected char (A)"))))
+
+
+ ;; slurping param name
+ ((= state 1)
+ (cond
+ ;; ws signifies the end of the param
+ ((string-match "[ \t\f\v\n\r]" cs)
+ (setq state 2))
+ ;; a legal char for an identifier
+ ((string-match "[A-Za-z_0-9]" cs)
+ t)
+ (t
+ (error "unexpected char (B)"))))
+
+
+ ;; ws between typespec and param name
+ ((= state 2)
+ (cond
+ ((string-match "[ \t\f\v\n\r]" cs)
+ t)
+ ;; non-ws indicates the type spec is beginning
+ (t
+ (incf i)
+ (setq state 3
+ need-type nil
+ nesting 0
+ ix2 i))))
+
+
+ ;; slurping type
+ ((= state 3)
+ (cond
+ ((= ?> c) (incf nesting))
+ ((= ?< c)
+ (decf nesting)
+ (setq need-type t))
+
+ ;; ws or comma maybe signifies the end of the typespec
+ ((string-match "[ \t\f\v\n\r,]" cs)
+ (if (and (= nesting 0) (not need-type))
+ (progn
+ (setq new (cons (substring s2 (1+ i) ix2) new))
+ (setq state
+ (if (= c ?,) 0 4)))))
- (cond
+ ((string-match "[A-Za-z_0-9]" cs)
+ (setq need-type nil))))
- ;; backing over whitespace "after" the param
- ((= state 0)
- (cond
- ;; more ws
- ((string-match "[ \t\f\v\n\r]" cs)
- t)
- ;; a legal char for an identifier
- ((string-match "[A-Za-z_0-9]" cs)
- (setq state 1))
- (t
- (error "unexpected char (A)"))))
-
-
- ;; slurping param name
- ((= state 1)
- (cond
- ;; ws signifies the end of the param
- ((string-match "[ \t\f\v\n\r]" cs)
- (setq state 2))
- ;; a legal char for an identifier
- ((string-match "[A-Za-z_0-9]" cs)
- t)
- (t
- (error "unexpected char (B)"))))
-
-
- ;; ws between typespec and param name
- ((= state 2)
- (cond
- ((string-match "[ \t\f\v\n\r]" cs)
- t)
- ;; non-ws indicates the type spec is beginning
- (t
- (incf i)
- (setq state 3
- need-type nil
- nesting 0
- ix2 i))))
-
-
- ;; slurping type
- ((= state 3)
- (cond
- ((= ?> c) (incf nesting))
- ((= ?< c)
- (decf nesting)
- (setq need-type t))
- ;; ws or comma maybe signifies the end of the typespec
- ((string-match "[ \t\f\v\n\r,]" cs)
- (if (and (= nesting 0) (not need-type))
- (progn
- (setq new (cons (substring s2 (1+ i) ix2) new))
- (setq state
- (if (= c ?,) 0 4)))))
+ ;; awaiting comma or b-o-s
+ ((= state 4)
+ (cond
- ((string-match "[A-Za-z_0-9]" cs)
- (setq need-type nil))))
+ ((= ?, c)
+ (if (= nesting 0)
+ (setq state 0)))
+ ((string-match "[ \t\f\v\n\r]" cs)
+ t)
- ;; awaiting comma or b-o-s
- ((= state 4)
- (cond
- ((= ?, c)
- (setq state 0))
+ ((= 93 c) (incf nesting)) ;; sq brack
+ ((= 91 c) ;; open sq brack
+ (decf nesting))
+
+ ;; handle this (extension methods), out, ref, params
+ ((and (>= i 5)
+ (string= (substring s2 (- i 5) (1+ i)) "params"))
+ (setf (car new) (concat "params " (car new)))
+ (setq i (- i 5)))
+
+ ((and (>= i 3)
+ (string= (substring s2 (- i 3) (1+ i)) "this"))
+ (setf (car new) (concat "this " (car new)))
+ (setq i (- i 3)))
+
+ ((and (>= i 2)
+ (string= (substring s2 (- i 2) (1+ i)) "ref"))
+ (setf (car new) (concat "ref " (car new)))
+ (setq i (- i 2)))
+
+ ((and (>= i 2)
+ (string= (substring s2 (- i 2) (1+ i)) "out"))
+ (setf (car new) (concat "out " (car new)))
+ (setq i (- i 2)))
+
+ (t
+ (error "unexpected char (C)"))))
+ )
+
+ (decf i))
+
+ (if (and (= state 3) (= nesting 0))
+ (setq new (cons (substring s2 i ix2) new)))
- ((string-match "[ \t\f\v\n\r,]" cs)
- t)
- (t
- (error "unexpected char (C)"))))
- )
+ (concat "("
+ (if new
+ (mapconcat 'identity new ", ")
+ "")
+ ")")))))
+
+(defun csharp--imenu-item-basic-comparer (a b)
+ "Compares the car of each element, assumed to be a string."
+ (string-lessp (car a) (car b)))
+
+
+(defun csharp--imenu-get-method-name-from-sig (sig)
+ "Extract a method name with its parameter list from a method
+signature, SIG. This is used to aid in sorting methods by name,
+and secondarily by parameter list.
+
+For this input:
+
+ private Dict<String, int> DoSomething(int, string)
+
+...the output is:
+
+ DoSomething(int, string)
+
+"
+ (let* (c
+ result
+ (state 0)
+ (len (length sig))
+ (i (1- len)))
+ (while (> i 0)
+ (setq c (aref sig i))
+
+ (cond
+ ((and (= state 0) (= c 40))
+ (setq state 1))
+
+ ((and (= state 1) (or (= c 9) (= c 32)))
+ (setq result (substring sig (1+ i))
+ i 0)))
(decf i))
+ result))
+
+
+
+(defun csharp--imenu-item-method-name-comparer (a b)
+ "Compares the method names in the respective cars of each element.
- (if (and (= state 3) (= nesting 0))
- (setq new (cons (substring s2 i ix2) new)))
+The car of each element is assumed to be a string with multiple
+tokens in it, representing a method signature, including access
+modifier, return type, and parameter list (surrounded by parens).
+If the method takes no params, then it's just an empty pair of
+parens.
- (concat "("
- (if new
- (mapconcat 'identity new ", ")
- "")
- ")")))
+This fn extracts the method name and param list from that
+signature and compares *that*.
+
+"
+ (let ((methoda (csharp--imenu-get-method-name-from-sig (car a)))
+ (methodb (csharp--imenu-get-method-name-from-sig (car b))))
+ ;;(csharp-log -1 "compare '%s' <> '%s'" methoda methodb)
+ (string-lessp methoda methodb)))
@@ -3199,9 +3487,21 @@ Upon entry, it's assumed that the parens included in S.
consider-usings
consider-namespaces)
"Helper fn for `csharp-imenu-create-index'.
-Scans for a namespace, then scans within the namespace for methods.
-Returns a list, suitable for use as an imenu index
-alist. Leaves point after close-curly on the namespace.
+Scans a possibly narrowed section of a c# buffer. It finds
+namespaces, classes, structs, enums, interfaces, and methods
+within classes and structs.
+
+The way it works: it looks for an open-curly. If the open-curly
+is a namespace or a class, it narrows to whatever is inside the
+curlies, then recurses.
+
+Otherwise (the open-curly is neither of those things), this fn
+tries to recognize the open-curly as the beginning of an enum,
+method, or interface.
+
+If it succeeds, then a menu item is created for the thing. Then
+it jumps to the matching close-curly, and continues. Stop when no
+more open-curlies are found.
"
@@ -3235,6 +3535,7 @@ alist. Leaves point after close-curly on the namespace.
;;
(let (container-name
+ (pos-last-curly -1)
this-flavor
this-item
this-menu
@@ -3253,32 +3554,52 @@ alist. Leaves point after close-curly on the namespace.
done nil))
((re-search-forward "{" (point-max) t)
- (let ((literal (csharp-in-literal)))
- ;; skip over comments?
- (if (memq literal '(c c++))
- (progn
- (while (memq literal '(c c++))
- (end-of-line)
+ (if (= pos-last-curly (point))
+ (progn
+ ;;(csharp-log -1 "imenu: No advance? quitting (%d)" (point))
+ (setq done t)) ;; haven't advanced- likely a loop
+
+ (setq pos-last-curly (point))
+ (let ((literal (csharp-in-literal)))
+ ;; skip over comments?
+ (cond
+
+ ((memq literal '(c c++))
+ (while (memq literal '(c c++))
+ (end-of-line)
+ (forward-char 1)
+ (setq literal (csharp-in-literal)))
+ (if (re-search-forward "{" (point-max) t)
+ (forward-char -1)
+ ;;(csharp-log -1 "imenu: No more curlies (A) (%d)" (point))
+ (setq done t)))
+
+ ((eq literal 'string)
+ (if (re-search-forward "\"" (point-max) t)
(forward-char 1)
- (setq literal (csharp-in-literal)))
- (if (re-search-forward "{" (point-max) t)
- (forward-char -1)
- (setq done t)))
+ ;;(csharp-log -1 "imenu: Never-ending string? posn(%d)"
(point))
+ (setq done t)))
- (forward-char -1)
- (setq done nil))))
+ (t
+ (forward-char -1)))))) ;; backup onto the curly
(t
+ ;;(csharp-log -1 "imenu: No more curlies (B) posn(%d)" (point))
(setq done t)))
(if (not done)
(cond
- ;; case 0: in a string or comment
- ((csharp-in-literal)
- t)
- ;; case 1: at the head of a block of using statements
+ ;; case 1: open curly for an array initializer
+ ((looking-back "\\[\\][ \t\n\r]*")
+ (forward-sexp 1))
+
+ ;; case 2: just jumped over a string
+ ((looking-back "\"")
+ (forward-char 1))
+
+ ;; case 3: at the head of a block of using statements
(found-usings
(setq found-usings nil
consider-usings nil) ;; only one batch
@@ -3299,14 +3620,10 @@ alist. Leaves point after close-curly on the namespace.
(push (cons marquis first-using) this-menu)))
- ;; case 2: an interface or enum inside the container
+ ;; case 4: an interface or enum inside the container
;; (must come before class / namespace )
((or (csharp--on-intf-open-curly-p)
(csharp--on-enum-open-curly-p))
- (let ((top (match-beginning 1))
- (close-curly (save-excursion
- (forward-sexp 1)
- (point))))
(setq consider-namespaces nil
consider-usings nil
this-menu
@@ -3316,13 +3633,14 @@ alist. Leaves point after close-curly on the namespace.
(match-string-no-properties 1) ;; thing
flavor
" "
(match-string-no-properties 2)) ;; intf
name
- top))))
+ (match-beginning 1)))))
+ (forward-sexp 1))
- (goto-char close-curly)))
- ;; case 3: at the start of a container (class, namespace)
+ ;; case 5: at the start of a container (class, namespace)
((or (and consider-namespaces (csharp--on-namespace-open-curly-p))
- (csharp--on-class-open-curly-p))
+ (csharp--on-class-open-curly-p)
+ (csharp--on-genclass-open-curly-p))
;; produce a fully-qualified name for this thing
(if (string= (match-string-no-properties 1) "namespace")
@@ -3344,7 +3662,6 @@ alist. Leaves point after close-curly on the namespace.
(close-curly (save-excursion
(forward-sexp 1)
(point))))
-
(setq submenu
(list
(concat this-flavor " " container-name)
@@ -3354,25 +3671,19 @@ alist. Leaves point after close-curly on the namespace.
(save-restriction
(narrow-to-region (1+ open-curly) (1- close-curly))
- (let ((child-menu
- (csharp--imenu-create-index-helper container-name
- (concat indent-level
" ")
- (string= this-flavor
"namespace")
- (string= this-flavor
"namespace"))))
- ;; there may be multiple children; add them all
+ (let* ((yok (string= this-flavor "namespace"))
+ (child-menu
+ (csharp--imenu-create-index-helper container-name
+ (concat
indent-level " ")
+ yok yok)))
(if child-menu
- (setq submenu (append submenu child-menu)))))
-
- ;; (setq m (make-marker)
- ;; submenu
- ;; (append submenu
- ;; (list
- ;; (cons "(bottom)" (set-marker m close-curly)))))
-
+ (setq submenu
+ (append submenu
+ (sort child-menu
+
'csharp--imenu-item-basic-comparer))))))
(setq submenu
(append submenu
- (list
- (cons "(bottom)" close-curly))))
+ (list (cons "(bottom)" close-curly))))
(setq this-menu
(append this-menu (list submenu)))
@@ -3380,30 +3691,23 @@ alist. Leaves point after close-curly on the namespace.
(goto-char close-curly)))
- ;; case 4: a property
+ ;; case 6: a property
((csharp--on-prop-open-curly-p)
- (let ((top (match-beginning 1))
- (close-curly (save-excursion
- (forward-sexp 1)
- (point))))
- (setq consider-namespaces nil
- consider-usings nil
- this-menu
- (append this-menu
- (list
- (cons (concat
- "prop "
- (match-string-no-properties 3)) ;; prop
name
- top))))
- (goto-char close-curly)))
-
- ;; case 5: an indexer
+ (setq consider-namespaces nil
+ consider-usings nil
+ this-menu
+ (append this-menu
+ (list
+ (cons (concat
+ "prop "
+ (match-string-no-properties 3)) ;; prop name
+ (match-beginning 1)))))
+ (forward-sexp 1))
+
+
+ ;; case 7: an indexer
((csharp--on-indexer-open-curly-p)
- (let ((top (match-beginning 1))
- (close-curly (save-excursion
- (forward-sexp 1)
- (point))))
- (setq consider-namespaces nil
+ (setq consider-namespaces nil
consider-usings nil
this-menu
(append this-menu
@@ -3411,56 +3715,49 @@ alist. Leaves point after close-curly on the namespace.
(cons (concat
"indexer "
(match-string-no-properties 4)) ;; index
type
- top ))))
-
- (goto-char close-curly)))
+ (match-beginning 1)))))
+ (forward-sexp 1))
- ;; case 6: a constructor inside the container
+ ;; case 8: a constructor inside the container
((csharp--on-ctor-open-curly-p)
- (let ((top (match-beginning 1))
- (close-curly (save-excursion
- (forward-sexp 1)
- (point))))
-
- (setq consider-namespaces nil
- consider-usings nil
- this-menu
- (append this-menu
- (list
- (cons (concat
- "ctor "
- (match-string-no-properties 2) ;; ctor name
-
(csharp--imenu-remove-param-names-from-paramlist
- (match-string-no-properties 3))) ;; ctor
params
- top))))
-
- (goto-char close-curly)))
-
-
- ;; case 7: a method inside the container
+ (setq consider-namespaces nil
+ consider-usings nil
+ this-menu
+ (append this-menu
+ (list
+ (cons (concat
+ "ctor "
+ (match-string-no-properties 2) ;; ctor name
+
(csharp--imenu-remove-param-names-from-paramlist
+ (match-string-no-properties 3))) ;; ctor
params
+ (match-beginning 1)))))
+ (forward-sexp 1))
+
+
+ ;; case 9: a method inside the container
((csharp--on-defun-open-curly-p)
- (let ((top (match-beginning 1))
- (close-curly (save-excursion
- (forward-sexp 1)
- (point))))
-
- (setq consider-namespaces nil
- consider-usings nil
- this-menu
- (append this-menu
- (list
- (cons (concat
- "method "
- (match-string-no-properties 2) ;; return
type
- " "
- (match-string-no-properties 3) ;; func name
-
(csharp--imenu-remove-param-names-from-paramlist
- (match-string-no-properties 4))) ;; fn
params
- top ))))
-
- (goto-char close-curly)))
-
+ (setq consider-namespaces nil
+ consider-usings nil
+ this-menu
+ (append this-menu
+ (list
+ (cons (concat
+ "method "
+ (match-string-no-properties 2) ;; return type
+ " "
+ (match-string-no-properties 3) ;; func name
+
(csharp--imenu-remove-param-names-from-paramlist
+ (match-string-no-properties 4))) ;; fn
params
+ (match-beginning 1)))))
+ (forward-sexp 1))
+
+
+ ;; case 10: unknown open curly - just jump over it.
+ ((looking-at "{")
+ (forward-sexp 1))
+
+ ;; case 11: none of the above. shouldn't happen?
(t
(forward-char 1)))))
@@ -3482,7 +3779,7 @@ alist. Leaves point after close-curly on the namespace.
;; designed to do the stuff for the menu generation.
-(defcustom csharp-imenu-max-similar-items-before-extraction 4
+(defcustom csharp-imenu-max-similar-items-before-extraction 6
"The maximum number of things of a particular
category (constructor, property, method, etc) that will be
separely displayed on an imenu without factoring them into a
@@ -3526,16 +3823,14 @@ see `csharp-want-imenu', and `csharp-mode'.
It had better be a string!"
(car (split-string s nil t)))
+
(defun csharp--make-plural (s)
- "make a work plural. For use within the generated imenu."
+ "make a word plural. For use within the generated imenu."
(cond
- ((string= s "prop")
- "properties")
- ((string= s "ctor")
- "constructors")
- (t
- (concat s "s"))))
-
+ ((string= s "prop") "properties")
+ ((string= s "class") "classes")
+ ((string= s "ctor") "constructors")
+ (t (concat s "s"))))
(defun csharp--imenu-counts (list)
@@ -3580,19 +3875,19 @@ the lookup table.
The reason it's a lookup table and not a simple arithmetic
function: I think it would look silly to have 2 submenus each
-with 12 items. Twelve of 14 items on a submenu seems fine when
-you're working through 120 items. But if you have only 20 items,
-better to have 3 items with 6 and 7 items each. That's what this
-lookup tries to do.
+with 24 items. Sixteen or 18 items on a submenu seems fine when
+you're working through 120 items total. But if you have only 28
+items, better to have 3 submenus with 10 and 9 items each. So
+it's not a linear function. That's what this lookup tries to do.
"
- (let ((size-pairs '((100 . 20)
- (80 . 18)
- (60 . 16)
+ (let ((size-pairs '((100 . 22)
+ (80 . 20)
+ (60 . 18)
(40 . 15)
- (30 . 12)
- (24 . 9)
- (0 . 7)))
+ (30 . 14)
+ (24 . 11)
+ (0 . 9)))
elt
(r 0))
@@ -3604,18 +3899,6 @@ lookup tries to do.
r))
-(defun csharp--imenu-item-basic-comparer (a b)
- "Compares the car of each element, assumed to be a string."
- (string-lessp (car a) (car b)))
-
-
-(defun csharp--imenu-item-last-word-comparer (a b)
- "Compares the last word in the car of each element. The car of
-each element is assumed to be a string with multiple tokens in it. "
- (let ((alast (car (last (split-string (car a) "[ \t]" t))))
- (blast (car (last (split-string (car b) "[ \t]" t)))))
- (string-lessp alast blast)))
-
(defun csharp--imenu-remove-category-names (menu-list)
"Input is a list, each element is (LABEL . LOCATION). This fn
@@ -3629,6 +3912,55 @@ returns a modified list, with the first word - the
category name
(cdr elt))))
menu-list))
+(defun string-indexof (s c)
+ "Returns the index of the first occurrence of character C in string S.
+Returns nil if not found.
+
+See also, `string-lastindexof'
+
+"
+ (let ((len (length s))
+ (i 0) ix c2)
+ (while (and (< i len) (not ix))
+ (setq c2 (aref s i))
+ (if (= c c2)
+ (setq ix i))
+ (incf i))
+ ix))
+
+(defun string-lastindexof (s c)
+ "Returns the index of the last occurrence of character C in string S.
+Returns nil if not found.
+
+See also, `string-indexof'
+
+"
+ (let ((i (length s))
+ ix c2)
+ (while (and (>= i 0) (not ix))
+ (setq c2 (aref s i))
+ (if (= c c2)
+ (setq ix i))
+ (decf i))
+ ix))
+
+
+(defun csharp--imenu-submenu-label (sig flavor)
+ "generate a submenu label from the given signature, SIG.
+The sig is a method signature, property type-and-name,
+constructor, and so on, indicated by FLAVOR.
+
+This fn returns a simple name that can be used in the label for a
+break out submenu.
+
+"
+ (if (string= flavor "method")
+ (let ((method-name (csharp--imenu-get-method-name-from-sig sig)))
+ (substring method-name 0 (string-indexof method-name 40)))
+ (substring sig (1+ (string-lastindexof sig 32)))))
+
+
+
(defun csharp--imenu-break-one-menu-into-submenus (menu-list)
"Parcels a flat list MENU-LIST up into smaller sublists. It tries
@@ -3652,7 +3984,7 @@ Returns a new list, containing sublists.
(csharp--imenu-remove-category-names
(sort menu-list
(if (string= (caar counts) "methods")
- 'csharp--imenu-item-last-word-comparer
+ 'csharp--imenu-item-method-name-comparer
'csharp--imenu-item-basic-comparer))))
;; is the length already pretty short?
@@ -3663,7 +3995,10 @@ Returns a new list, containing sublists.
menu-list)
(t
- (let* ((lst (sort menu-list 'csharp--imenu-item-basic-comparer))
+ (let* ((lst (sort menu-list
+ (if (string= (caar counts) "methods")
+ 'csharp--imenu-item-method-name-comparer
+ 'csharp--imenu-item-basic-comparer)))
new
(sz (csharp--imenu-get-submenu-size len)) ;; goal max size of
sublist
(n (ceiling (/ (* 1.0 len) sz))) ;; total number of sublists
@@ -3671,7 +4006,6 @@ Returns a new list, containing sublists.
(nsmall (mod (- adj-sz (mod len adj-sz)) adj-sz)) ;; num of (n-1)
lists
(i 0)
(base-name (csharp--first-word (caar lst)))
- (plural-name (csharp--make-plural base-name))
label
chunksz
this-chunk)
@@ -3681,7 +4015,8 @@ Returns a new list, containing sublists.
this-chunk (csharp--imenu-remove-category-names
(nthcdr (- len chunksz) lst))
lst (nbutlast lst chunksz)
- label (format "%s %d" plural-name (- n i))
+ ;;label (format "%s %d" plural-name (- n i))
+ label (concat "from " (csharp--imenu-submenu-label (caar
this-chunk) base-name))
new (cons (cons label this-chunk) new)
len (- len chunksz))
(incf i))
@@ -3703,106 +4038,111 @@ possibly break a submenu into smaller sublists, based
on size.
-(defun csharp--imenu-reorg-flat-alist-intelligently (menu-alist)
- "Accepts an imenu alist. Returns an alist, each item is a cons
-cell where the car is a unique first word that appears in the car of
-each element of LIST, and the cdr is a list of the cdrs of each
-of the corresponding unique element in the original list.
-It's easier to understand than it is to explain.
-Before:
+(defun csharp--imenu-reorg-alist-intelligently (menu-alist)
+ "Accepts an imenu alist. Returns an alist, reorganized.
+Things get sorted, factored out into category submenus,
+and split into multiple submenus, where conditions warrant.
- ((\"usings (4)\" . #<marker at 1538 in ZipFile.cs>)
+For example, suppose this imenu alist is generated from a scan:
+
+ ((\"usings (4)\" . 1538)
(\"namespace Ionic.Zip\"
- (\"(top)\" . #<marker at 1651 in ZipFile.cs>)
+ (\"(top)\" . 1651)
(\"partial class Ionic.Zip.ZipFile\"
- (\"(top)\" . #<marker at 5473 in ZipFile.cs>)
- (\"prop FullScan\" . #<marker at 8036 in ZipFile.cs>)
+ (\"(top)\" . 5473)
+ (\"prop FullScan\" . 8036)
...
- (\"prop Comment\" . #<marker at 21118 in ZipFile.cs>)
- (\"prop Verbose\" . #<marker at 32278 in ZipFile.cs>)
- (\"method override String ToString\" . #<marker at 96577 in ZipFile.cs>)
- (\"method internal void NotifyEntryChanged\" . #<marker at 97608 in
ZipFile.cs>)
+ (\"prop Comment\" . 21118)
+ (\"prop Verbose\" . 32278)
+ (\"method override String ToString\" . 96577)
+ (\"method internal void NotifyEntryChanged\" . 97608)
....
- (\"method internal void Reset\" . #<marker at 98231 in ZipFile.cs>)
- (\"ctor ZipFile\" . #<marker at 103598 in ZipFile.cs>)
+ (\"method internal void Reset\" . 98231)
+ (\"ctor ZipFile\" . 103598)
...
- (\"ctor ZipFile\" . #<marker at 109723 in ZipFile.cs>)
- (\"ctor ZipFile\" . #<marker at 116487 in ZipFile.cs>)
- (\"indexer int\" . #<marker at 121232 in ZipFile.cs>)
- (\"indexer String\" . #<marker at 124933 in ZipFile.cs>)
- (\"(bottom)\" . #<marker at 149777 in ZipFile.cs>))
- (\"public enum Zip64Option\" . #<marker at 153839 in ZipFile.cs>)
- (\"enum AddOrUpdateAction\" . #<marker at 154815 in ZipFile.cs>)
- (\"(bottom)\" . #<marker at 154893 in ZipFile.cs>)))
+ (\"ctor ZipFile\" . 109723)
+ (\"ctor ZipFile\" . 116487)
+ (\"indexer int\" . 121232)
+ (\"indexer String\" . 124933)
+ (\"(bottom)\" . 149777))
+ (\"public enum Zip64Option\" . 153839)
+ (\"enum AddOrUpdateAction\" . 154815)
+ (\"(bottom)\" . 154893)))
This is displayed as a toplevel menu with 2 items; the namespace
menu has 5 items (top, bottom, the 2 enums, and the class). The
-class menu has 93 items. Unworkable.
+class menu has 93 items. It needs to be reorganized to be more usable.
-After:
+After transformation of the alist through this fn, the result is:
- ((\"usings (4)\" . #<marker at 1538 in ZipFile.cs>)
+ ((\"usings (4)\" . 1538)
(\"namespace Ionic.Zip\"
- (\"(top)\" . #<marker at 1651 in ZipFile.cs>)
+ (\"(top)\" . 1651)
(\"partial class Ionic.Zip.ZipFile\"
- (\"(top)\" . #<marker at 5473 in ZipFile.cs>)
- (\"prop\"
- (\"prop WriteStream\" . #<marker at 146489 in ZipFile.cs>)
- (\"prop Count\" . #<marker at 133827 in ZipFile.cs>)
+ (\"(top)\" . 5473)
+ (\"properties\"
+ (\"WriteStream\" . 146489)
+ (\"Count\" . 133827)
....
- (\"prop BufferSize\" . #<marker at 12837 in ZipFile.cs>)
- (\"prop FullScan\" . #<marker at 8036 in ZipFile.cs>))
- (\"method\"
- (\"method virtual void Dispose\" . #<marker at 144389 in ZipFile.cs>)
- (\"method void RemoveEntry\" . #<marker at 141027 in ZipFile.cs>)
+ (\"BufferSize\" . 12837)
+ (\"FullScan\" . 8036))
+ (\"methods\"
+ (\"virtual void Dispose\" . 144389)
+ (\"void RemoveEntry\" . 141027)
....
- (\"method override String ToString\" . #<marker at 96577 in
ZipFile.cs>)
- (\"method bool ContainsEntry\" . #<marker at 32517 in ZipFile.cs>))
- (\"ctor\"
- (\"ctor ZipFile\" . #<marker at 116487 in ZipFile.cs>)
+ (\"method override String ToString\" . 96577)
+ (\"method bool ContainsEntry\" . 32517))
+ (\"constructors\"
+ (\"ZipFile\" . 116487)
....
- (\"ctor ZipFile\" . #<marker at 105698 in ZipFile.cs>)
- (\"ctor ZipFile\" . #<marker at 103598 in ZipFile.cs>))
- (\"indexer int\" . #<marker at 121232 in ZipFile.cs>)
- (\"indexer String\" . #<marker at 124933 in ZipFile.cs>)
- (\"(bottom)\" . #<marker at 149777 in ZipFile.cs>))
- (\"public enum Zip64Option\" . #<marker at 153839 in ZipFile.cs>)
- (\"enum AddOrUpdateAction\" . #<marker at 154815 in ZipFile.cs>)
- (\"(bottom)\" . #<marker at 154893 in ZipFile.cs>)))
+ (\"ZipFile\" . 105698)
+ (\"ZipFile\" . 103598))
+ (\"indexer int\" . 121232)
+ (\"indexer String\" . 124933)
+ (\"(bottom)\" . 149777))
+ (\"public enum Zip64Option\" . 153839)
+ (\"enum AddOrUpdateAction\" . 154815)
+ (\"(bottom)\" . 154893)))
All menus are the same except the class menu, which has been
-organized into subtopics, each of which gets its own cascaded submenu.
+organized into subtopics, each of which gets its own cascaded
+submenu. If the submenu itself holds more than
+`csharp-imenu-max-similar-items-before-extraction' items that are
+all the same flavor (properties, methods, etc), thos get split
+out into multiple submenus.
"
(let ((counts (csharp--imenu-counts menu-alist)))
-
- (flet ((helper (list new)
- (if (null list)
- new
- (let* ((elt (car list))
- (topic (csharp--make-plural (csharp--first-word
(car elt))))
- (xelt (assoc topic new)))
- (helper (cdr list)
- (if xelt
- (progn
- (rplacd xelt (cons elt (cdr xelt)))
- new)
- (cons
-
- (cond
- ((> (cdr (assoc topic counts))
csharp-imenu-max-similar-items-before-extraction )
- (cons topic (list elt)))
-
- ((imenu--subalist-p elt)
- (cons (car elt)
-
(csharp--imenu-reorg-flat-alist-intelligently (cdr elt))))
- (t
- elt))
-
- new)))))))
+ (flet ((helper
+ (list new)
+ (if (null list)
+ new
+ (let* ((elt (car list))
+ (topic (csharp--make-plural (csharp--first-word (car
elt))))
+ (xelt (assoc topic new)))
+ (helper
+ (cdr list)
+ (if xelt
+ (progn
+ (rplacd xelt (cons elt (cdr xelt)))
+ new)
+ (cons
+
+ (cond
+ ((> (cdr (assoc topic counts))
+ csharp-imenu-max-similar-items-before-extraction)
+ (cons topic (list elt)))
+
+ ((imenu--subalist-p elt)
+ (cons (car elt)
+ (csharp--imenu-reorg-alist-intelligently (cdr
elt))))
+ (t
+ elt))
+
+ new)))))))
(csharp--imenu-break-into-submenus
(nreverse (helper menu-alist nil))))))
@@ -3872,7 +4212,7 @@ attempts to disable the weird re-jiggering that imenu
performs.
(let ((index-alist
(csharp--imenu-create-index-helper nil "" t t)))
- (csharp--imenu-reorg-flat-alist-intelligently index-alist)
+ (csharp--imenu-reorg-alist-intelligently index-alist)
;;index-alist
@@ -3917,22 +4257,22 @@ attempts to disable the weird re-jiggering that imenu
performs.
- ;; ==================================================================
- ;; 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.
+;; ==================================================================
+;; 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)
+(defun csharp-maybe-insert-codedoc (arg)
- "Insert an xml code documentation template as appropriate, when
+ "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
@@ -3959,289 +4299,289 @@ 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-event)
- (cb0 (char-before (- (point) 0)))
- (cb1 (char-before (- (point) 1)))
- is-first-non-whitespace
- did-auto-insert
- )
-
- ;; check if two prior chars were slash, in other words,
- ;; check if this is the third slash in a row.
- (if (and (= char ?/) cb0 (= ?/ cb0) cb1 (= ?/ cb1))
+ (interactive "*p")
+ ;;(message "csharp-maybe-insert-codedoc")
+ (let (
+ (cur-point (point))
+ (char last-command-event)
+ (cb0 (char-before (- (point) 0)))
+ (cb1 (char-before (- (point) 1)))
+ is-first-non-whitespace
+ did-auto-insert
+ )
+
+ ;; check if two prior chars were slash, in other words,
+ ;; check if this is the third slash in a row.
+ (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
- (forward-line -1)
- (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 "/ <summary>\n/// \n/// </summary>"
- 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 "/ <remarks>\n/// <para>\n///
\n/// </para>\n/// </remarks>"
- 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 "/ <example>\n/// \n/// </example>"
- 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 "/ <returns></returns>"
- 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<para>\n///%s
\n///%s</para>"
- 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///
</para>\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))
+ (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
+ (forward-line -1)
+ (beginning-of-line)
+ (looking-at "[
\t]*$\\|[ \t]*{[ \t]*$"))))
+ (flavor 0) ;; used only for diagnostic purposes
+ )
- ;; set the flag, that we actually inserted text
- (setq did-auto-insert t)
+ ;;(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 "/ <summary>\n/// \n/// </summary>"
+ 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 "/ <remarks>\n/// <para>\n///
\n/// </para>\n/// </remarks>"
+ 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 "/ <example>\n/// \n/// </example>"
+ 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 "/ <returns></returns>"
+ 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<para>\n///%s
\n///%s</para>"
+ 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///
</para>\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))
- ;; save point of beginning of insertion
- (setq cur-point (point))
+ ;; set the flag, that we actually inserted text
+ (setq did-auto-insert t)
- ;; actually insert the text
- (insert text-to-insert)
+ ;; save point of beginning of insertion
+ (setq cur-point (point))
- ;; 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)
+ ;; actually insert the text
+ (insert text-to-insert)
- (let ((newline-count 0) (pos 0) ix)
+ ;; 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)
- ;; 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) )
- )
+ (let ((newline-count 0) (pos 0) ix)
- ;; indent what we just inserted
- (c-indent-region cur-point (point) t)
+ ;; 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) )
+ )
- ;; 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.
- (forward-line (- 0 (/ newline-count 2)))
- (end-of-line)))))))))
+ ;; indent what we just inserted
+ (c-indent-region cur-point (point) t)
- (if (not did-auto-insert)
- (self-insert-command (prefix-numeric-value arg)))))
+ ;; 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.
+ (forward-line (- 0 (/ newline-count 2)))
+ (end-of-line)))))))))
- ;; ==================================================================
- ;; end of c# code-doc insertion magic
- ;; ==================================================================
+ (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.
- ;;
+
+;; ==================================================================
+;; 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'.")
+;; ;; 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'.")
- (defun csharp-time ()
- "returns the time of day as a string. Used in the `csharp-log' function."
- (substring (current-time-string) 11 19)) ;24-hr time
+(defun csharp-time ()
+ "returns the time of day as a string. Used in the `csharp-log' function."
+ (substring (current-time-string) 11 19)) ;24-hr time
- (defun csharp-log (level text &rest args)
- "Log a message at level LEVEL.
+(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 "C# %s %s" (cscomp-time) msg))))
+ (if (<= level csharp-log-level)
+ (let* ((msg (apply 'format text args)))
+ (message "C# %s %s" (csharp-time) msg))))
- (defun csharp-max-beginning-of-stmt ()
- "Return the greater of `c-beginning-of-statement-1' and
+(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)))
+ (let (dash
+ nodash
+ (curpos (point)))
- ;; I think this may need a save-excursion...
- ;; Calling c-beginning-of-statement-1 resets the 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 "max-bostmt dash(%d)" dash)
- (goto-char curpos)
+ (setq dash (progn (c-beginning-of-statement-1) (point)))
+ (csharp-log 3 "max-bostmt dash(%d)" dash)
+ (goto-char curpos)
- (setq nodash (progn (c-beginning-of-statement 1) (point)))
- (csharp-log 3 "max-bostmt nodash(%d)" nodash)
- (goto-char curpos)
+ (setq nodash (progn (c-beginning-of-statement 1) (point)))
+ (csharp-log 3 "max-bostmt nodash(%d)" nodash)
+ (goto-char curpos)
- (max dash nodash)))
+ (max dash nodash)))
- (defun csharp-set-vliteral-syntax-table-properties (beg end)
- "Scan the buffer text between BEG and END, a verbatim literal
+(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.
@@ -4256,72 +4596,72 @@ for the list of syntax table numeric codes.
"
- (csharp-log 3 "set-vlit-syntax-table: beg(%d) end(%d)" beg end)
+ (csharp-log 3 "set-vlit-syntax-table: beg(%d) end(%d)" beg end)
- (if (and (> beg 0) (> end 0))
+ (if (and (> beg 0) (> end 0))
- (let ((curpos beg)
- (state 0))
+ (let ((curpos beg)
+ (state 0))
- (c-clear-char-properties beg end 'syntax-table)
+ (c-clear-char-properties beg end 'syntax-table)
- (while (<= curpos end)
+ (while (<= curpos end)
+ (cond
+ ((= state 0)
+ (if (= (char-after curpos) ?@)
+ (progn
+ (c-put-char-property curpos 'syntax-table '(6)) ; (6) =
expression prefix, (3) = symbol
+ ;;(message (format "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 "set-s-t: open quote pos(%d) chr(%c)"
+ ;; curpos (char-after curpos)))
+ ))
+ (setq state (+ 1 state)))
+
+ ((= state 2)
(cond
- ((= state 0)
- (if (= (char-after curpos) ?@)
- (progn
- (c-put-char-property curpos 'syntax-table '(6)) ; (6) =
expression prefix, (3) = symbol
- ;;(message (format "set-s-t: prefix pos(%d) chr(%c)" beg
(char-after beg)))
- )
- )
- (setq state (+ 1 state)))
+ ;; handle backslash inside the string
+ ((= (char-after curpos) ?\\)
+ (c-put-char-property curpos 'syntax-table '(2)) ; (1) =
punctuation, (2) = word
+ ;;(message (format "set-s-t: backslash word pos(%d) chr(%c)"
curpos (char-after curpos)))
+ )
- ((= state 1)
- (if (= (char-after curpos) ?\")
- (progn
- (c-put-char-property curpos 'syntax-table '(7)) ; (7) =
string quote
- ;;(message (format "set-s-t: open quote 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 "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 "set-s-t: close quote pos(%d) chr(%c)" curpos
(char-after curpos)))
+ ;;go no further
(setq state (+ 1 state)))
- ((= state 2)
- (cond
- ;; handle backslash inside the string
- ((= (char-after curpos) ?\\)
- (c-put-char-property curpos 'syntax-table '(2)) ; (1) =
punctuation, (2) = word
- ;;(message (format "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 "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 "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 "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
+ ;; everything else
+ (t
+ ;;(message (format "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.
@@ -4329,37 +4669,37 @@ 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 "end-of-vlit-string: point(%d) c(%c)" (point) (char-after))
+ (csharp-log 3 "end-of-vlit-string: point(%d) c(%c)" (point) (char-after))
- (let (curpos
- (max (or lim (point-max))))
+ (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))
+ (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
+ ;; 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)))
+ (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
+(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.
@@ -4382,135 +4722,136 @@ 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)
+ (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 "verblit scan")
+ (goto-char curpos)
+
+ (while (and (< curpos lastpos) (< cycle 10000))
+ (cond
- (csharp-log 3 "scan")
- (goto-char curpos)
+ ;; Case 1: current char is a @ sign
+ ;; --------------------------------------------
+ ;; Check to see if it demarks the beginning of a verblit
+ ;; string.
+ ((= ?@ (char-after curpos))
- (while (and (< curpos lastpos) (< cycle 10000))
+ ;; 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: current char is a @ sign
+ ;; Case 1.A: it's a @ within a string.
;; --------------------------------------------
- ;; 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 "scan: jump end comment A (%d)" (cdr
limits))
- (setq curpos (cdr limits)))))
+ ;; 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 "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))))
+ ;; 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 "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
- (setq eos (csharp-end-of-verbatim-literal-string))
- ;; set override syntax properties on the verblit string
- (csharp-set-vliteral-syntax-table-properties curpos eos)
+ ;; Case 2.A: a quote within a string
+ ;; --------------------------------------------
+ ;; This shouldn't happen, because we hop over strings.
+ ;; But it might.
+ ((eq literal 'string) nil)
- (csharp-log 4 "scan: jump end verblit string (%d)" eos)
- (setq curpos eos))))
+ ;; 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 "scan: jump end comment B (%s)" curpos))))
- ;; Case 2: current char is a double-quote.
+ ;; Case 2.C: Not in a comment, and not in a string.
;; --------------------------------------------
- ;; 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 "scan: jump end comment B (%s)" curpos))))
-
+ ;; 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 "scan: jump end literal (%d)" (cdr limits))
+ (setq curpos (cdr limits))))))))
- ;; 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 "scan: jump end literal (%d)" (cdr limits))
- (setq curpos (cdr limits))))))))
+ (setq cycle (+ 1 cycle))
+ (setq curpos (+ 1 curpos))
+ (c-safe (goto-char curpos)))))))
- (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
+(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'.
@@ -4527,40 +4868,42 @@ 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)))
+ (csharp-log 2 "before font lock %d %d %d %d" beg end old-len (point))
+ (let ((start-scan (progn
+ ;; is this right? I think
+ (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)
+(c-lang-defconst c-before-font-lock-function
+ csharp 'csharp--before-font-lock)
- ;; ==================================================================
- ;; end of c# fontification extensions
- ;; ==================================================================
+;; ==================================================================
+;; end of c# fontification extensions
+;; ==================================================================
- ;; ==================================================================
- ;; C#-specific optimizations of cc-mode funcs
- ;; ==================================================================
+;; ==================================================================
+;; C#-specific optimizations of cc-mode funcs
+;; ==================================================================
- ;; 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)
- )
+;; 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
- ;; ==================================================================
+;; ==================================================================
+;; end of C#-specific optimizations of cc-mode funcs
+;; ==================================================================
@@ -4569,371 +4912,371 @@ The return value is meaningless, and is ignored by
cc-mode.
- ;; ==================================================================
- ;; c# - monkey-patching of basic parsing logic
- ;; ==================================================================
+;; ==================================================================
+;; c# - monkey-patching of basic parsing logic
+;; ==================================================================
+;;
+;; The following 2 defuns redefine functions from cc-mode, to add
+;; special cases for C#. 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.
;;
- ;; The following 2 defuns redefine functions from cc-mode, to add
- ;; special cases for C#. 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.
+ ;; 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.
- (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))))
-
-
-
-
-
- (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-safe (c-forward-sexp -1))
- (let (bracepos)
- (if (and (or (looking-at c-brace-list-key)
-
- (progn
- (c-safe (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-safe (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 ((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[
\t\n\f\v\r]+\\([[: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))))
+
+
+
+
+
+(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
- (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)
+ (goto-char containing-sexp)
+ (c-safe (c-forward-sexp -1))
+ (let (bracepos)
+ (if (and (or (looking-at c-brace-list-key)
+
+ (progn
+ (c-safe (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-safe (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
- (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.
+ (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)
- (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 `<opchar>= 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))
- ))
+ (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 `<opchar>= 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
- ;; ==================================================================
+;; ==================================================================
+;; 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)))
+;;(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 . +)
- ))
- ))
+(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 . +)
+ ))
+ ))
@@ -5020,7 +5363,6 @@ an entry for csharp, in your .emacs file:
(setq auto-mode-alist
(append '((\"\\.cs$\" . csharp-mode)) auto-mode-alist))
-
The mode provides fontification and indent for C# syntax, as well
as some other handy features.
@@ -5189,6 +5531,8 @@ Key bindings:
(set (make-local-variable 'parse-sexp-lookup-properties) t)
;; scan the entire buffer for verblit strings
+ ;; This will happen on font; it's necessary only
+ ;; if font-lock is disabled. But it won't hurt.
(csharp-scan-for-verbatim-literals-and-set-props nil nil)
;; Allow fill-paragraph to work on xml code doc
- [elpa] externals/csharp-mode 3414c63 006/459: First check in of Cscomp - C# code completion., (continued)
- [elpa] externals/csharp-mode 3414c63 006/459: First check in of Cscomp - C# code completion., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 756f086 003/459: Few updates to csharp-mode. First checkin of aspx-mode.el, for ASPX files., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 03ed8fb 016/459: v0.8.4 - fixes bug with yasnippet integration, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode afe5315 022/459: Add GPL v2 license as found in the original project on Google Code., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode e940015 023/459: Update readme-file., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode d657aa0 025/459: Fix error in heading., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 2a28871 026/459: clean out unused files, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 77cbcf4 030/459: Add byte-compilation, unit-test running to makefile., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 35d295d 008/459: Fix a problem with parsing in csharp-completion.el, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 9f66d3b 011/459: fix doc to remove mention of flymake-command, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode c47e9ea 017/459: v0.8.5 - updates to imenu, fontification,
ELPA Syncer <=
- [elpa] externals/csharp-mode 1119177 018/459: Small update in string-lastindexof, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 287f044 031/459: Automatically detect version during package-build based on elisp-content., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode bd1d83e 044/459: Updated readme., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode d33cfb6 046/459: Update readme with note about MELPA stable., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode b286555 054/459: Ensure csharp-mode calls `prog-mode` hooks., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 78293bd 029/459: Add proper makefile for creating and publishing packages., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 44718a3 007/459: Update of csharp-mode.el - version # is now 0.7.6, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 4fc9fad 010/459: Update C# completion stuff, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode f6965a6 015/459: v0.8.3 - imenu, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode c1e2c49 024/459: Gitignore for Emacs and Elisp., ELPA Syncer, 2021/08/22