[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/csharp-mode 497a70e 009/459: Simplify csharp-mode; elim
From: |
ELPA Syncer |
Subject: |
[elpa] externals/csharp-mode 497a70e 009/459: Simplify csharp-mode; eliminate flymake-for-csharp.el (unnecessary) |
Date: |
Sun, 22 Aug 2021 13:58:44 -0400 (EDT) |
branch: externals/csharp-mode
commit 497a70e0916544f3d4d05626e4d5905267a9c7c9
Author: Dino Chiesa <dpchiesa@hotmail.com>
Commit: Dino Chiesa <dpchiesa@hotmail.com>
Simplify csharp-mode; eliminate flymake-for-csharp.el (unnecessary)
---
Readme.txt | 44 +-
csharp-mode.el | 3248 +++++++++++++++++++++++++++++++++++++++-----------------
2 files changed, 2285 insertions(+), 1007 deletions(-)
diff --git a/Readme.txt b/Readme.txt
index 888c57f..0a19f30 100644
--- a/Readme.txt
+++ b/Readme.txt
@@ -1,10 +1,10 @@
-Mon, 24 May 2010 17:21
+Created Mon, 24 May 2010 17:21
+Updated Fri, 13 May 2011 13:02
This is the readme for csharp-mode.
You can use csharp-mode alone. To do so,
-
put this in your .emacs:
(autoload 'csharp-mode "csharp-mode" "Major mode for editing C# code." t)
@@ -28,42 +28,10 @@ You can use csharp-mode alone. To do so,
=======================================================
-You can also take advantage of C# code completion.
-To do so, put csharp-completion.el, csharp-shell.el , and powershell.el
-on your load-path.
-
-You must also have semantic, from the CEDET package, on your load path.
-
-Put the CscompUtilities.dll in the same location as csharp-shell.el.
-
-Put this in your .emacs file:
-
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; C# code completion (requires CEDET semantic)
-
- (setq load-path
- (append '("~/users/dinoch/elisp/cedet/semantic"
- "~/users/dinoch/elisp/cedet/semantic/bovine"
- "~/users/dinoch/elisp/cedet/common"
- "~/users/dinoch/elisp/cedet/eieio"
- "~/users/dinoch/elisp/cedet/contrib"
- ) load-path ))
-
- (load "semantic")
- (load "semantic-load")
- (load "wisent-csharp")
-
- (require 'csharp-completion)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-
-In your csharp-mode-hook, bind a key to the cscomp completion trigger.
-Like this:
-
- ;; C# code completion
- (local-set-key "\M-\\" 'cscomp-complete-at-point)
- (local-set-key "\M-\." 'cscomp-complete-at-point-menu)
+The c# code completion is undergoing some changes.
+For now, don't use it.
+=======================================================
+x-URL: http://code.google.com/p/csharpmode/
diff --git a/csharp-mode.el b/csharp-mode.el
index 6e2d57d..4389e4c 100644
--- a/csharp-mode.el
+++ b/csharp-mode.el
@@ -3,11 +3,11 @@
;; Author : Dylan R. E. Moonfire (original)
;; Maintainer : Dino Chiesa <dpchiesa@hotmail.com>
;; Created : Feburary 2005
-;; Modified : April 2010
-;; Version : 0.7.6
+;; Modified : May 2011
+;; Version : 0.8.2
;; Keywords : c# languages oop mode
;; X-URL : http://code.google.com/p/csharpmode/
-;; Last-saved : <2010-May-24 21:53:58>
+;; Last-saved : <2011-May-13 11:59:16>
;;
;; This program is free software; you can redistribute it and/or modify
@@ -27,8 +27,9 @@
;;; Commentary:
;;
-;; This is a separate mode to implement the C# constructs and
-;; font-locking. It is based on the java-mode example from cc-mode.
+;; This is a major mode for editing C# code. It performs automatic
+;; indentation of C# syntax; font locking; integration with compile.el;
+;; integration with flymake.el; integration with yasnippet.el.
;;
;; csharp-mode requires CC Mode 5.30 or later. It works with
;; cc-mode 5.31.3, which is current at this time.
@@ -47,35 +48,155 @@
;;
;; - automagic code-doc generation when you type three slashes.
;;
-;; - intelligent inserttion of matched pairs of curly braces.
+;; - intelligent insertion of matched pairs of curly braces.
;;
-;; - sets the compiler regex for next-error, for csc.exe output.
+;; - compile tweaks. Infers the compile command from special comments
+;; in the file header. Also, sets the regex for next-error, so that
+;; compile.el can handle csc.exe output.
;;
+;; - flymake integration
+;; - select flymake command from code comments
+;; - infer flymake command otherwise (presence of makefile, etc)
+;; - Turn off query-on-exit-flag for the flymake process.
+;; - define advice to flymake-goto-line , to allow it to goto the
+;; appropriate column for the error on a given line. This works
+;; with `flymake-goto-next-error' etc.
;;
+;; - yasnippet integration
+;; - preloaded snippets
+;; -?
-;;; To use:
+
+;; Installation instructions
+;; --------------------------------
;;
-;; put this in your .emacs:
+;; Put csharp-mode.el somewhere in your load path, optionally byte-compile
+;; it, and add the following to your .emacs file:
;;
;; (autoload 'csharp-mode "csharp-mode" "Major mode for editing C# code." t)
-;;
-;; or:
-;;
-;; (require 'csharp-mode)
+;; (setq auto-mode-alist
+;; (append '(("\\.cs$" . csharp-mode)) auto-mode-alist))
;;
;;
-;; AND:
+;; Optionally, define and register a mode-hook function. To do so, use
+;; something like this in your .emacs file:
;;
-;; (setq auto-mode-alist
-;; (append '(("\\.cs$" . csharp-mode)) auto-mode-alist))
;; (defun my-csharp-mode-fn ()
;; "function that runs when csharp-mode is initialized for a buffer."
-;; ...insert your code here...
-;; ...most commonly, your custom key bindings ...
+;; (turn-on-auto-revert-mode)
+;; (setq indent-tabs-mode nil)
+;; (require 'flymake)
+;; (flymake-mode 1)
+;; (require 'yasnippet)
+;; (yas/minor-mode-on)
+;; (require 'rfringe)
+;; ...insert more code here...
+;; ...including any custom key bindings you might want ...
;; )
;; (add-hook 'csharp-mode-hook 'my-csharp-mode-fn t)
;;
;;
+;; General
+;; ----------------------------
+;;
+;; Mostly C# mode will "just work." Use `describe-mode' to see the
+;; default keybindings and the highlights of the mode.
+;;
+;;
+;; Flymake Integration
+;; ----------------------------
+;;
+;; You can use flymake with csharp mode to automatically check the
+;; syntax of your csharp code, and highlight errors. To do so, add a
+;; comment line like this to each .cs file that you use flymake with:
+;;
+;; // flymake-command: c:\.net3.5\csc.exe /t:module /nologo /R:Foo.dll
+;;
+;; That lines specifies a command "stub". Flymake appends the name of
+;; the file to compile, and then runs the command to check
+;; syntax. Flymake assumes that syntax errors will be noted in the
+;; output of the command in a form that fits one of the regexs in the
+;; `compilation-error-regexp-alist-alist'. Check the flymake module for
+;; more information on that.
+;;
+;; Some rules for the command:
+;;
+;; 1. it must appear all on a single line.
+;;
+;; 2. csharp-mode generally looks for the marker line in the first N
+;; lines of the file, where N is set in
+;; `csharp-cmd-line-limit'. See the documentation on that
+;; variable for more information.
+;;
+;; 3. the command SHOULD NOT include the name of the source file
+;; currently being edited. This is because flymake saves a copy of
+;; the buffer into a temporary file with a unique name, and then
+;; compiles that temporary file. The name of the temporary file is
+;; automatically appended to the end of the command. The command
+;; should include /R options specifying external libraries that
+;; the code depends on.
+;;
+;; If you have no external dependencies, then you need not specify any
+;; flymake-command at all. csharp-mode will implicitly act as ifyou had
+;; specified the command:
+;;
+;; // flymake-command: c:\.net3.5\csc.exe /t:module /nologo
+;;
+;;
+;; If you use csc.exe as the syntax check tool (as almost everyone
+;; will), the /t:module is important. csharp-mode assumes that the
+;; syntax-check compile command will produce a file named
+;; NAME.netmodule, which is the default when using /t:module. (Remember
+;; than NAME is dynamically generated). csharp-mode will remove the
+;; generated netmodule file after the syntax check is complete. If you
+;; don't specify /t:module, then csharp-mode won't know what file to
+;; delete.
+;;
+;; csharp-mode also fiddles with some other flymake things. In
+;; particular it: adds .cs to the flymake "allowed filename masks";
+;; adds parsing for csc error messages; and adds advice to the error
+;; parsing logic. This all should be pretty benign for all other
+;; flymake buffers. But it might not be.
+;;
+;; You can explicitly turn the flymake integration for C# off by
+;; setting `csharp-want-flymake-fixup' to nil.
+;;
+;;
+;; Compile Integration
+;; ----------------------------
+;;
+;; csharp-mode binds the function `csharp-invoke-compile-interactively'
+;; to "\C-x\C-e" . This function attempts to intellgently guess the
+;; format of the compile command to use for a buffer. It looks in the
+;; comments at the head of the buffer for a line that begins with
+;; compile: . If found, csharp-mode suggests the text that follows as
+;; the compilation command when running `compile' . If such a line is
+;; not found, csharp-mode falls back to a msbuild or nmake command.
+;; See the documentation on `csharp-cmd-line-limit' for further
+;; information.
+;;
+;; Also, csharp-mode installs an error regexp for csc.exe into
+;; `compilation-error-regexp-alist-alist', which allows `next-error'
+;; and `previous-error' (defined in compile.el) to navigate to the next
+;; and previous compile errors in the cs buffer, after you've run `compile'.
+;;
+;;
+;; YASnippet integration
+;; -----------------------------
+;;
+;; csharp-mode defines some built-in snippets for
+;; convenience. For example, if statements, for, foreach, and
+;; so on. You can see them on the YASnippet menu that is displayed
+;; when a csharp-mode buffer is opened. csharp-mode defines this
+;; snippets happens only if ya-snippet is available. (It is done in an
+;; `eval-after-load' clause.) The builtin snippets will not overwrite
+;; snippets that use the same name, if they are defined in the normal
+;; way (in a compiled bundle) with ya-snippet.
+;;
+;; You can explicitly turn off ya-snippet integration. See the var,
+;; `csharp-want-yasnippet-fixup'.
+;;
+;;
;;; Known Bugs:
;;
@@ -162,7 +283,7 @@
;; - intelligent curly-brace insertion
;; 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
+;; - fixed a bug that had crept into the codedoc insertion.
;; 0.7.5 - now fontify namespaces in the using statements. This is
;; done in the csharp value for c-basic-matchers-before .
;; - also fontify the name following namespace decl.
@@ -174,12 +295,25 @@
;; - Constructors are now fontified.
;; - Field/Prop names inside object initializers are now fontified.
;;
-
-
+;; 0.7.7 - relocate running c-run-mode-hooks to the end of
+;; csharp-mode, to allow user to modify key bindings in a
+;; hook if he doesn't like the defaults.
;;
+;; 0.7.8 - redefine csharp-log to insert timestamp.
+;;
+;; - Fix byte-compile errors on emacs 23.2 ? Why was
+;; c-filter-ops duplicated here? What is the purpose of its
+;; presence here, I am not clear.
+;;
+;; 0.8.0 - include flymake magic into this module.
+;; - include yasnippet integration
+;;
+;; 0.8.2 - small tweaks; now set a one-time bool for flymake installation
+;; - some doc updates on flymake
(require 'cc-mode)
+;;(require 'cl)
(message (concat "Loading " load-file-name))
@@ -188,39 +322,43 @@
;; c# upfront stuff
;; ==================================================================
-;; This is a copy of the function in cc-mode which is used to handle
-;; the eval-when-compile which is needed during other times.
-(defun c-filter-ops (ops opgroup-filter op-filter &optional xlate)
- ;; See cc-langs.el, a direct copy.
- (unless (listp (car-safe ops))
- (setq ops (list ops)))
- (cond ((eq opgroup-filter t)
- (setq opgroup-filter (lambda (opgroup) t)))
- ((not (functionp opgroup-filter))
- (setq opgroup-filter `(lambda (opgroup)
- (memq opgroup ',opgroup-filter)))))
- (cond ((eq op-filter t)
- (setq op-filter (lambda (op) t)))
- ((stringp op-filter)
- (setq op-filter `(lambda (op)
- (string-match ,op-filter op)))))
- (unless xlate
- (setq xlate 'identity))
- (c-with-syntax-table (c-lang-const c-mode-syntax-table)
- (delete-duplicates
- (mapcan (lambda (opgroup)
- (when (if (symbolp (car opgroup))
- (when (funcall opgroup-filter (car opgroup))
- (setq opgroup (cdr opgroup))
- t)
- t)
- (mapcan (lambda (op)
- (when (funcall op-filter op)
- (let ((res (funcall xlate op)))
- (if (listp res) res (list res)))))
- opgroup)))
- ops)
- :test 'equal)))
+;; This is a copy of the function in cc-mode which is used to handle the
+;; eval-when-compile which is needed during other times.
+;;
+;; NB: I think this is needed to satisfy requirements when this module
+;; calls `c-lang-defconst'. (DPC)
+
+;; (defun c-filter-ops (ops opgroup-filter op-filter &optional xlate)
+;; ;; See cc-langs.el, a direct copy.
+;; (unless (listp (car-safe ops))
+;; (setq ops (list ops)))
+;; (cond ((eq opgroup-filter t)
+;; (setq opgroup-filter (lambda (opgroup) t)))
+;; ((not (functionp opgroup-filter))
+;; (setq opgroup-filter `(lambda (opgroup)
+;; (memq opgroup ',opgroup-filter)))))
+;; (cond ((eq op-filter t)
+;; (setq op-filter (lambda (op) t)))
+;; ((stringp op-filter)
+;; (setq op-filter `(lambda (op)
+;; (string-match ,op-filter op)))))
+;; (unless xlate
+;; (setq xlate 'identity))
+;; (c-with-syntax-table (c-lang-const c-mode-syntax-table)
+;; (delete-duplicates
+;; (mapcan (lambda (opgroup)
+;; (when (if (symbolp (car opgroup))
+;; (when (funcall opgroup-filter (car opgroup))
+;; (setq opgroup (cdr opgroup))
+;; t)
+;; t)
+;; (mapcan (lambda (op)
+;; (when (funcall op-filter op)
+;; (let ((res (funcall xlate op)))
+;; (if (listp res) res (list res)))))
+;; opgroup)))
+;; ops)
+;; :test 'equal)))
@@ -229,6 +367,7 @@
;; related constants could additionally be put inside an
;; (eval-after-load "font-lock" ...) but then some trickery is
;; necessary to get them compiled.)
+
(eval-when-compile
(let ((load-path
(if (and (boundp 'byte-compile-dest-file)
@@ -255,9 +394,40 @@
;; ==================================================================
-;; csharp-mode utility and feature defuns
+;; constants used in this module
;; ==================================================================
+;;(error (byte-compile-dest-file))
+;;(error (c-get-current-file))
+
+(defconst csharp-aspnet-directive-re
+ "<%@.+?%>"
+ "Regex for matching directive blocks in ASP.NET files (.aspx, .ashx, .ascx)")
+
+(defconst csharp-enum-decl-re
+ (concat
+ "\\<enum[ \t\n\r\f\v]+"
+ "\\([[:alpha:]_][[:alnum:]_]*\\)"
+ "[ \t\n\r\f\v]*"
+ "\\(:[ \t\n\r\f\v]*"
+ "\\("
+ (c-make-keywords-re nil
+ (list "sbyte" "byte" "short" "ushort" "int" "uint" "long" "ulong"))
+ "\\)"
+ "\\)?")
+ "Regex that captures an enum declaration in C#"
+ )
+
+;; ==================================================================
+
+
+
+
+
+
+;; ==================================================================
+;; csharp-mode utility and feature defuns
+;; ==================================================================
(defun csharp-at-vsemi-p (&optional pos)
"Determines if there is a virtual semicolon at POS or point.
@@ -283,7 +453,6 @@ 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))))
@@ -369,6 +538,39 @@ Another option is to use `csharp-lineup-region'.
+ (defun csharp-in-literal (&optional lim detect-cpp)
+ "Return the type of literal point is in, if any.
+Basically this works like `c-in-literal' except it doesn't
+use or fill the cache (`c-in-literal-cache').
+
+The return value is `c' if in a C-style comment, `c++' if in a C++
+style comment, `string' if in a string literal, `pound' if DETECT-CPP
+is non-nil and in a preprocessor line, or nil if somewhere else.
+Optional LIM is used as the backward limit of the search. If omitted,
+or nil, `c-beginning-of-syntax' is used.
+
+Note that this function might do hidden buffer changes. See the
+comment at the start of cc-engine.el for more info."
+
+ (let ((rtn
+ (save-excursion
+ (let* ((pos (point))
+ (lim (or lim (progn
+ (c-beginning-of-syntax)
+ (point))))
+ (state (parse-partial-sexp lim pos)))
+ (csharp-log 4 "parse lim(%d) state: %s" lim (prin1-to-string
state))
+ (cond
+ ((elt state 3)
+ (csharp-log 4 "in literal string (%d)" pos)
+ 'string)
+ ((elt state 4)
+ (csharp-log 4 "in literal comment (%d)" pos)
+ (if (elt state 7) 'c++ 'c))
+ ((and detect-cpp (c-beginning-of-macro lim)) 'pound)
+ (t nil))))))
+ rtn))
+
(defun csharp-insert-open-brace ()
"Intelligently insert a pair of curly braces. This fn is most
@@ -450,7 +652,7 @@ Another option is to use `csharp-lineup-region'.
(newline)
(insert "};")
(c-indent-region tpoint (point))
- (previous-line)
+ (forward-line -1)
(indent-according-to-mode)
(end-of-line)
(setq tpoint (point)))
@@ -486,7 +688,7 @@ Another option is to use `csharp-lineup-region'.
(insert "}")
;;(c-indent-command) ;; not sure of the difference here
(c-indent-line-or-region)
- (previous-line)
+ (forward-line -1)
(end-of-line)
(newline-and-indent)
;; point ends up on an empty line, within the braces, properly indented
@@ -501,49 +703,10 @@ Another option is to use `csharp-lineup-region'.
-
-
-
;; ==================================================================
;; c# values for "language constants" defined in cc-langs.el
;; ==================================================================
-
-;; Java uses a series of regexes to change the font-lock for class
-;; references. The problem comes in because Java uses Pascal (leading
-;; space in names, SomeClass) for class and package names, but
-;; Camel-casing (initial lowercase, upper case in words,
-;; i.e. someVariable) for variables. The notation suggested by EMCA for C# is
-;; to use Pascal notation for everything, except inner variables. So,
-;; the Java regex and formatting produces very wrong results in C#.
-;;(error (byte-compile-dest-file))
-;;(error (c-get-current-file))
-
-(defconst csharp-aspnet-directive-re
- "<%@.+?%>"
- "Regex for matching directive blocks in ASP.NET files (.aspx, .ashx, .ascx)")
-
-(defconst csharp-enum-decl-re
- (concat
- "\\<enum[ \t\n\r\f\v]+"
- "\\([[:alpha:]_][[:alnum:]_]*\\)"
- "[ \t\n\r\f\v]*"
- "\\(:[ \t\n\r\f\v]*"
- "\\("
- (c-make-keywords-re nil
- (list "sbyte" "byte" "short" "ushort" "int" "uint" "long" "ulong"))
- "\\)"
- "\\)?")
- "Regex that captures an enum declaration in C#"
- )
-
-
-
-;; X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+
-
-;; vsemi's allow proper indentation of code that includes inline
-;; attributes and ASPNET directives. These are c#-specific things that
-;; need custom treatment.
(c-lang-defconst c-at-vsemi-p-fn
csharp 'csharp-at-vsemi-p)
@@ -1052,11 +1215,8 @@ Another option is to use `csharp-lineup-region'.
(c-put-font-lock-face (match-beginning 3)
(match-end 3)
'font-lock-function-name-face))
- (goto-char (match-end 0))
- )
- ))
- nil))
- )))
+ (goto-char (match-end 0)))))
+ nil)))))
;; Case 4: using clause. Without this, using (..) gets fontified as
a fn.
@@ -1399,9 +1559,7 @@ Another option is to use `csharp-lineup-region'.
;; variable here, to provide the regex explicitly.
;;
(c-lang-defconst c-decl-block-key
-
- csharp
'"\\(namespace\\)\\([^[:alnum:]_]\\|$\\)\\|\\(class\\|interface\\|struct\\)\\([^[:alnum:]_]\\|$\\)"
- )
+ csharp
'"\\(namespace\\)\\([^[:alnum:]_]\\|$\\)\\|\\(class\\|interface\\|struct\\)\\([^[:alnum:]_]\\|$\\)"
)
@@ -1525,10 +1683,133 @@ Another option is to use `csharp-lineup-region'.
;; preprocessor support, so include it.
(c-lang-const c-cpp-matchers)))
-(defcustom csharp-font-lock-extra-types nil
- "*List of extra types (aside from the type keywords) to recognize in C# mode.
-Each list item should be a regexp matching a single identifier."
- :type 'list :group 'csharp)
+
+
+;; Custom variables
+;;;###autoload
+(defcustom csharp-mode-hook nil
+ "*Hook called by `csharp-mode'."
+ :type 'hook
+ :group 'csharp)
+
+
+ ;; The following fn allows this:
+ ;; (csharp-log 3 "scan result...'%s'" state)
+
+ (defcustom csharp-log-level 0
+ "The current log level for CSharp-mode-specific operations.
+This is used in particular by the verbatim-literal
+string scanning.
+
+Most other csharp functions are not instrumented.
+0 = NONE, 1 = Info, 2 = VERBOSE, 3 = DEBUG, 4 = SHUTUP ALREADY. "
+ :type 'integer
+ :group 'csharp)
+
+
+;;;###autoload
+(defcustom csharp-want-flymake-fixup t
+ "*Whether to enable the builtin C# support for flymake. This is meaningful
+only if flymake is loaded."
+ :type 'boolean :group 'csharp)
+
+;;;###autoload
+(defcustom csharp-want-yasnippet-fixup t
+ "*Whether to enable the builtin C# support for yasnippet. This is meaningful
+only if flymake is loaded."
+ :type 'boolean :group 'csharp)
+
+
+;;;###autoload
+(defcustom csharp-make-tool "nmake"
+ "*The make tool to use. Defaults to nmake, found on path. Specify
+a full path or alternative program name, to tell csharp-mode to use
+a different make tool in compile commands.
+
+See also, `csharp-msbuild-tool'.
+
+"
+ :type 'string :group 'csharp)
+
+
+;;;###autoload
+(defcustom csharp-msbuild-tool "msbuild"
+ "*The tool to use to build .csproj files. Defaults to msbuild, found on
+path. Specify a full path or alternative program name, to tell csharp-mode
+to use a different make tool in compile commands.
+
+See also, `csharp-make-tool'.
+
+"
+ :type 'string :group 'csharp)
+
+
+;;;###autoload
+(defcustom csharp-cmd-line-limit 28
+ "The number of lines at the top of the file to look in, to find
+the command that csharp-mode will use to compile the current
+buffer, or the command \"stub\" that csharp-mode will use to
+check the syntax of the current buffer via flymake.
+
+If the value of this variable is zero, then csharp-mode looks
+everywhere in the file. If the value is positive, then only in
+the first N lines. If negative, then only in the final N lines.
+
+The line should appear in a comment inside the C# buffer.
+
+
+Compile
+--------
+
+In the case of compile, the compile command must be prefixed with
+\"compile:\". For example,
+
+ // compile: csc.exe /r:Hallo.dll Arfie.cs
+
+
+This command will be suggested as the compile command when the
+user invokes `compile' for the first time.
+
+
+Flymake
+--------
+
+In the case of flymake, the command \"stub\" string must be
+prefixed with \"flymake-command:\". For example,
+
+ // flymake-command: DOTNETDIR\csc.exe /target:netmodule /r:foo.dll
+
+In the case of flymake-command, the string should NOT
+include the name of the file for the buffer being checked.
+csharp-mode appends the name of the source file to compile, to
+this command \"stub\" before passing the command to flymake to
+run it.
+
+If for some reason the command is invalid or illegal, flymake
+will report an error and disable itself.
+
+
+In all cases
+------------
+
+Be sure to specify the proper path for your csc.exe, whatever
+version that might be, or no path if you want to use the system
+PATH search.
+
+If the buffer depends on external libraries, then you will want
+to include /R arguments to that csc.exe command.
+
+To be clear, this variable sets the number of lines to search for
+the command. This cariable is an integer.
+
+If the marker string (either \"compile:\" or \"flymake-command:\"
+is present in the given set of lines, csharp-mode will take
+anything after the marker string as the command to run.
+
+"
+ :type 'integer :group 'csharp)
+
+
(defconst csharp-font-lock-keywords-1 (c-lang-const c-matchers-1 csharp)
"Minimal highlighting for C# mode.")
@@ -1542,6 +1823,7 @@ Each list item should be a regexp matching a single
identifier."
(defvar csharp-font-lock-keywords csharp-font-lock-keywords-3
"Default expressions to highlight in C# mode.")
+
(defvar csharp-mode-syntax-table nil
"Syntax table used in csharp-mode buffers.")
(or csharp-mode-syntax-table
@@ -1565,6 +1847,37 @@ Each list item should be a regexp matching a single
identifier."
"Keymap used in csharp-mode buffers.")
+(defvar csharp--yasnippet-has-been-fixed nil
+ "indicates whether yasnippet has been patched for use with csharp.
+Intended for internal use only.")
+
+(defvar csharp--flymake-has-been-installed nil
+ "one-time use boolean, to check whether csharp tweaks for flymake (advice
etc)
+have been installed.")
+
+
+(defvar csharp-flymake-csc-arguments
+ (list "/t:module" "/nologo")
+ "A list of arguments to use with the csc.exe
+compiler, when using flymake with a
+direct csc.exe build for syntax checking purposes.")
+
+
+(defvar csharp-flymake-aux-error-info nil
+ "a list of auxiliary flymake error info items. Each item in the
+list is a pair, consisting of a line number and a column number.
+This info is set by advice to flymake-parse-line, and used by
+advice attached to flymake-goto-line, to navigate to the proper
+error column when possible. ")
+
+
+(defvar csharp-flymake-csc-error-pattern
+ "^[ \t]*\\([_A-Za-z0-9][^(]+\\.cs\\)(\\([0-9]+\\)[,]\\([0-9]+\\)) ?:
\\(\\(error\\|warning\\) CS[0-9]+:[ \t\n]*\\(.+\\)\\)"
+ "The regex pattern for C# compiler error messages. Follows
+the same form as an entry in `flymake-err-line-patterns'. The
+value is a STRING, a
+regex.")
+
;; TODO
;; Defines our constant for finding attributes.
;;(defconst csharp-attribute-regex "\\[\\([XmlType]+\\)(")
@@ -1585,372 +1898,906 @@ Each list item should be a regexp matching a single
identifier."
-;; ==================================================================
-;; 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)
+;; ========================================================================
+;; Flymake integration
- "Insert an xml code documentation template as appropriate, when
-typing slashes. This fn gets bound to / (the slash key), in
-csharp-mode. If the slash being inserted is not the third
-consecutive slash, the slash is inserted as normal. If it is the
-third consecutive slash, then a xml code documentation template
-may be inserted in some cases. For example,
+(defun csharp-flymake-init ()
+ (csharp-flymake-init-impl
+ 'flymake-create-temp-inplace t t 'csharp-flymake-get-cmdline))
- a <summary> template is inserted if the prior line is empty,
- or contains only an open curly brace;
- a <remarks> template is inserted if the prior word
- closes the <summary> element;
- a <returns> template is inserted if the prior word
- closes the <remarks> element;
- an <example> template is inserted if the prior word closes
- the <returns> element;
- a <para> template is inserted if the prior word closes
- a <para> element.
+(defun csharp-flymake-init-impl (create-temp-f use-relative-base-dir
use-relative-source get-cmdline-f)
+ "Create syntax check command line for a directly checked source file.
+Use CREATE-TEMP-F for creating temp copy."
+ (let* ((args nil)
+ (temp-source-file-name (flymake-init-create-temp-buffer-copy
create-temp-f)))
+ (setq args (flymake-get-syntax-check-program-args
+ temp-source-file-name "."
+ use-relative-base-dir use-relative-source
+ get-cmdline-f))
+ args))
-In all other cases the slash is inserted as normal.
-If you want the default cc-mode behavior, which implies no automatic
-insertion of xml code documentation templates, then use this in
-your `csharp-mode-hook' function:
+(defun csharp-flymake-cleanup ()
+ "Delete the temporary .netmodule file created in syntax checking
+a C# buffer, then call through to flymake-simple-cleanup."
- (local-set-key (kbd \"/\") 'c-electric-slash)
+ (if flymake-temp-source-file-name
+ (progn
+ (let* ((netmodule-name
+ (concat (file-name-sans-extension
flymake-temp-source-file-name)
+ ".netmodule"))
+ (expanded-netmodule-name (expand-file-name netmodule-name ".")))
+ (if (file-exists-p expanded-netmodule-name)
+ (flymake-safe-delete-file expanded-netmodule-name)))
+ ))
+ (flymake-simple-cleanup))
- "
- (interactive "*p")
- ;;(message "csharp-maybe-insert-codedoc")
- (let (
- (cur-point (point))
- (char last-command-char)
- (cb0 (char-before (- (point) 0)))
- (cb1 (char-before (- (point) 1)))
- is-first-non-whitespace
- did-auto-insert
- )
-
- ;; check if two prior chars were slash
- (if (and
- (= char ?/)
- cb0 (= ?/ cb0)
- cb1 (= ?/ cb1)
- )
- (progn
- ;;(message "yes - this is the third consecutive slash")
- (setq is-first-non-whitespace
- (save-excursion
- (back-to-indentation)
- (= cur-point (+ (point) 2))))
-
- (if is-first-non-whitespace
- ;; This is a 3-slash sequence. It is the first non-whitespace
text
- ;; on the line. Now we need to examine the surrounding context
- ;; in order to determine which xml cod doc template to insert.
- (let (word-back char0 char1
- word-fore char-0 char-1
- text-to-insert ;; text to insert in lieu of slash
- fn-to-call ;; func to call after inserting text
- (preceding-line-is-empty (or
- (= (line-number-at-pos) 1)
- (save-excursion
- (previous-line)
- (beginning-of-line)
- (looking-at "[ \t]*$\\|[ \t]*{[
\t]*$"))))
- (flavor 0) ;; used only for diagnostic purposes
- )
+(defun csharp-split-string-respecting-quotes (s)
+ "splits a string into tokens, respecting double quotes
+For example, the string 'This is \"a string\"' will be split into 3 tokens.
- ;;(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))
+More pertinently, the string
+ 'csc /t:module /R:\"c:\abba dabba\dooo\Foo.dll\"'
- ;; set the flag, that we actually inserted text
- (setq did-auto-insert t)
+...will be split into 3 tokens.
- ;; save point of beginning of insertion
- (setq cur-point (point))
+This fn also removes quotes from the tokens that have them. This is for
+compatibility with flymake and the process-start fn.
- ;; actually insert the text
- (insert text-to-insert)
+"
+ (let ((local-s s)
+ (my-re-1 "[^ \"]+\"[^\"]+\"\\|[^ \"]+")
+ (my-re-2 "\\([^ \"]+\\)\"\\([^\"]+\\)\"")
+ (tokens))
+ (while (string-match my-re-1 local-s)
+ (let ((token (match-string 0 local-s))
+ (remainder (substring local-s (match-end 0))))
+ (if (string-match my-re-2 token)
+ (setq token (concat (match-string 1 token) (match-string 2
token))))
+ ;;(message "token: %s" token)
+ (setq tokens (append tokens (list token)))
+ (setq local-s remainder)))
+ tokens))
- ;; indent the inserted string, and re-position point,
either through
- ;; the case-specific fn, or via the default progn.
- (if fn-to-call
- (funcall fn-to-call)
- (let ((newline-count 0) (pos 0) ix)
+(defun csharp-get-value-from-comments (marker-string line-limit)
+ "gets a string from the header comments in the current buffer.
- ;; 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) )
- )
+This is used to extract the flymake command and the compile
+command from the comments.
- ;; indent what we just inserted
- (c-indent-region cur-point (point) t)
+It looks for \"marker-string:\" and returns the string that
+follows it, or returns nil if that string is not found.
- ;; move up n/2 lines. This assumes that the
- ;; inserted text is ~symmetric about the halfway
point.
- ;; The assumption holds if the xml code doc uses a
- ;; begin-elt and end-elt on a new line all by
themselves,
- ;; and a blank line in between them where the point
should be.
- ;; A more intelligent implementation would use a
specific
- ;; marker string, like @@DOT, to note the desired
point.
- (previous-line (/ newline-count 2))
- (end-of-line)))))))))
+eg, when marker-string is \"flymake\", and the following
+string is found at the top of the buffer:
- (if (not did-auto-insert)
- (self-insert-command (prefix-numeric-value arg)))))
+ flymake: csc.exe /r:Hallo.dll
-;; ==================================================================
-;; end of c# code-doc insertion magic
-;; ==================================================================
+...then this command will return the string
+ \"csc.exe /r:Hallo.dll\"
+It's ok to have whitespace between the marker and the following
+colon.
+"
-;; ==================================================================
-;; c# fontification extensions
-;; ==================================================================
-;; Commentary:
+ (let (start search-limit found)
+ ;; determine what lines to look in
+ (save-excursion
+ (save-restriction
+ (widen)
+ (cond ((> line-limit 0)
+ (goto-char (setq start (point-min)))
+ (forward-line line-limit)
+ (setq search-limit (point)))
+ ((< line-limit 0)
+ (goto-char (setq search-limit (point-max)))
+ (forward-line line-limit)
+ (setq start (point)))
+ (t ;0 => no limit (use with care!)
+ (setq start (point-min))
+ (setq search-limit (point-max))))))
+
+ ;; look in those lines
+ (save-excursion
+ (save-restriction
+ (widen)
+ (let ((re-string
+ (concat "\\b" marker-string "[ \t]*:[ \t]*\\(.+\\)$")))
+ (if (and start
+ (< (goto-char start) search-limit)
+ (re-search-forward re-string search-limit 'move))
+
+ (buffer-substring-no-properties
+ (match-beginning 1)
+ (match-end 1))))))))
+
+
+
+
+(defun csharp-replace-command-tokens (explicitly-specified-command)
+ "Replace tokens in the flymake or compile command extracted from the
+buffer, to allow specification of the original and modified
+filenames.
+
+ @@ORIG@@ - gets replaced with the original filename
+ @@FILE@@ - gets replaced with the name of the temporary file
+ created by flymake
+
+"
+ (let ((massaged-command explicitly-specified-command))
+ (if (string-match "@@SRC@@" massaged-command)
+ (setq massaged-command
+ (replace-match
+ (file-relative-name flymake-temp-source-file-name) t t
massaged-command)))
+ (if (string-match "@@ORIG@@" massaged-command)
+ (setq massaged-command
+ (replace-match
+ (file-relative-name buffer-file-name) t t massaged-command)))
+ massaged-command))
+
+
+;;(setq flymake-log-level 3)
+
+(defun csharp-flymake-get-final-csc-arguments (initial-arglist)
+ "Gets the command used by csc.exe for flymake runs.
+This may inject a /t:module into an arglist, where it is not
+present.
+
+This fn burps if a different /t: argument is found.
+
+"
+ (interactive)
+ (let ((args initial-arglist)
+ arg
+ (found nil))
+ (while args
+ (setq arg (car args))
+ (cond
+ ((string-equal arg "/t:module") (setq found t))
+ ((string-match "^/t:" arg)
+ (setq found t)
+ (message "csharp-mode: WARNING /t: option present in arglist, and not
/t:module; fix this.")))
+
+ (setq args (cdr args)))
+
+ (setq args
+ (if found
+ initial-arglist
+ (append (list "/t:module") initial-arglist)))
+
+ (if (called-interactively-p 'any)
+ (message "result: %s" (prin1-to-string args)))
+
+ args))
+
+
+(defun csharp-flymake-get-cmdline (source base-dir)
+ "Gets the cmd line for running a flymake session in a C# buffer.
+This gets called by flymake itself.
+
+The fn looks in the buffer for a line that looks like:
+
+ flymake: <command goes here>
+
+ (It should be embedded into a comment)
+
+Typically the command will be a line that runs nmake.exe,
+msbuild.exe, or csc.exe, with various options. It should
+eventually run the CSC.exe compiler, or something else that emits
+error messages in the same form as the C# compiler.
+
+Some notes on implementation:
+
+ 1. csharp-mode copies the buffer to a temporary file and
+ 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
+ refer to it.
+
+ If you want to refer to it implicitly, you can use the special
+ token \"@@SRC@@\" in the command. It will get replaced with the
+ name of the temporary file at runtime. If you want to refer to
+ the original name of the buffer, use @@ORIG@@.
+
+ 2. In general, when running the compiler, you should use a
+ target type of \"module\" (eg, /t:module) to allow
+ csharp-mode to clean up the products of the build.
+
+ 3. See `csharp-cmd-line-limit' for a way to restrict where
+ csharp-mode will search for the command.
+
+ 4. If this string is not found, then this fn will fallback to
+ a generic, generated csc.exe command.
+
+"
+ (let ((explicitly-specified-command
+ (csharp-get-value-from-comments "flymake" csharp-cmd-line-limit)))
+
+ (cond
+ (explicitly-specified-command
+
+ ;; the marker string was found in the buffer
+ (let ((tokens (csharp-split-string-respecting-quotes
+ (csharp-replace-command-tokens
explicitly-specified-command))))
+
+ (list (car tokens) (cdr tokens))))
+
+ ;; ;; implicitly append? the name of the temporary source file
+ ;; (list (car tokens) (append (cdr tokens) (list
flymake-temp-source-file-name)))))
+
+ (t
+ ;; fallback
+ (list "csc.exe"
+ (append (csharp-flymake-get-final-csc-arguments
+ csharp-flymake-csc-arguments)
+ (list source)))))))
+
+
+;; (defun csharp-flymake-get-cmdline (source base-dir)
+;; "Gets the cmd line for running a flymake session in a C# buffer.
+;; This gets called by flymake itself.
+;;
+;; The fn looks in the buffer for a line that looks like:
+;;
+;; flymake-command: <command goes here>
+;;
+;; (It should be embedded into a comment)
;;
-;; 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 @"...".
+;; Typically the command will be a line that runs nmake.exe,
+;; msbuild.exe, or cscc.exe, with various options. It should
+;; eventually run the CSC.exe compiler, or something else that emits
+;; error messages in the same form as the C# compiler.
;;
-;; `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.
+;; In general, when running the compiler, you should use a target
+;; type of \"module\" (eg, /t:module) to allow csharp-mode to
+;; clean up the products of the build.
;;
-;; This is an attempt to fix that.
+;; See `csharp-cmd-line-limit' for a way to restrict where
+;; csharp-mode will search for the command.
;;
-;; 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.
+;; If this string is not found, then this fn will fallback to a
+;; generic, generated csc.exe command.
;;
-;; Also need to re-scan after any changes in the buffer, but on a more
-;; limited region.
+;; "
+;; (let ((explicitly-specified-command
+;; (let ((line-limit csharp-cmd-line-limit)
+;; start search-limit found)
+;; ;; determine what lines to look in
+;; (save-excursion
+;; (save-restriction
+;; (widen)
+;; (cond ((> line-limit 0)
+;; (goto-char (setq start (point-min)))
+;; (forward-line line-limit)
+;; (setq search-limit (point)))
+;; ((< line-limit 0)
+;; (goto-char (setq search-limit (point-max)))
+;; (forward-line line-limit)
+;; (setq start (point)))
+;; (t ;0 => no limit (use with
care!)
+;; (setq start (point-min))
+;; (setq search-limit (point-max))))))
;;
+;; ;; look in those lines
+;; (save-excursion
+;; (save-restriction
+;; (widen)
+;; (if (and start
+;; (< (goto-char start) search-limit)
+;; (re-search-forward "\\bflymake-command[ \t]*:[
\t]*\\(.+\\)$" search-limit 'move))
+;;
+;; (buffer-substring-no-properties
+;; (match-beginning 1)
+;; (match-end 1))))))))
+;;
+;; (cond
+;; (explicitly-specified-command
+;; ;; the marker string was found in the buffer
+;; (let ((tokens (csharp-split-string-respecting-quotes
+;; explicitly-specified-command)))
+;; ;; implicitly append the name of the temporary source file
+;; (list (car tokens) (append (cdr tokens) (list
flymake-temp-source-file-name)))))
+;;
+;; (t
+;; ;; fallback
+;; (list "csc.exe"
+;; (append (csharp-flymake-get-final-csc-arguments
+;; csharp-flymake-csc-arguments)
+;; (list source)))))))
-;; ;; 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'.")
-;; The following fn allows this:
-;; (csharp-log 3 "scan result...'%s'" state)
-(defvar csharp-log-level 0
- "The current log level for CSharp-specific operations.
-This is used in particular by the verbatim-literal
-string scanning.
-Most other csharp functions are not instrumented.
-0 = NONE, 1 = Info, 2 = VERBOSE, 3 = DEBUG, 4 = SHUTUP ALREADY. ")
-(defun csharp-log (level text &rest args)
- "Log a message at level LEVEL.
+(defun csharp-flymake-install ()
+
+ "Change flymake variables and fns to work with C#.
+
+This fn does these things:
+
+1. add a C# entry to the flymake-allowed-file-name-masks,
+ or replace it if it already exists.
+
+2. add a C# entry to flymake-err-line-patterns.
+ This isn't strictly necessary because of item #4.
+
+3. override the definition for flymake-process-sentinel
+ to NOT check the process status on exit. MSBuild.exe
+ sets a non-zero status code when compile errors occur,
+ which causes flymake to disable itself with the regular
+ flymake-process-sentinel.
+
+4. redefine flymake-start-syntax-check-process to unset the
+ query-on-exit flag for flymake processes. This allows emacs to
+ exit even if flymake is currently running.
+
+5. provide advice to flymake-parse-line and
+ flymake-parse-err-lines, specifically set up for C#
+ buffers. This allows optimized searching for errors in csc.exe
+ output, and storing column numbers, for use in #6.
+
+6. define advice to flymake-goto-line , to allow it to goto the
+ appropriate column for the error on a given line. This advice
+ looks in flymake-er-info, a list, and uses the heuristic that
+ the first error that matches the given line number, is the error
+ we want. This will break if there is more than one error on a
+ single line.
+
+"
+
+ (flymake-log 2 "csharp-flymake-install")
+
+ (or csharp--flymake-has-been-installed
+ (progn
+
+ ;; 1. add a C# entry to the flymake-allowed-file-name-masks
+ (let* ((key "\\.cs\\'")
+ (csharpentry (assoc key flymake-allowed-file-name-masks)))
+ (if csharpentry
+ (setcdr csharpentry '(csharp-flymake-init csharp-flymake-cleanup))
+ (add-to-list
+ 'flymake-allowed-file-name-masks
+ (list key 'csharp-flymake-init 'csharp-flymake-cleanup))))
+
+
+ ;; 2. add a C# entry to flymake-err-line-patterns
+ ;;
+ ;; The value of each entry is a list, (STRING IX1 IX2 IX3 IX4), where
+ ;; STRING is the regex, and the other 4 values are indexes into the
+ ;; regex captures for the filename, line, column, and error text,
+ ;; respectively.
+ (add-to-list
+ 'flymake-err-line-patterns
+ (list csharp-flymake-csc-error-pattern 1 2 3 4))
+
+
+
+ ;; 3. override the definition for flymake-process-sentinel
+ ;;
+ ;; DPC - 2011 Feb 26
+ ;; Redefining a function is a bit unusual, but I think it is necessary
+ ;; to remove the check on process exit status. For VBC.exe, it gives
+ ;; a 1 status when compile errors result. Likewise msbuild.exe. This
+ ;; means flymake turns itself off, which we don't want. This really
+ ;; ought to be tunable in flymake, but I guess no one asked for that
+ ;; feature yet.
+ (defun flymake-process-sentinel (process event)
+ "Sentinel for syntax check buffers."
+ (when (memq (process-status process) '(signal exit))
+ (let* ((exit-status (process-exit-status process))
+ (command (process-command process))
+ (source-buffer (process-buffer process))
+ (cleanup-f (flymake-get-cleanup-function
(buffer-file-name source-buffer))))
+
+ (flymake-log 2 "process %d exited with code %d"
+ (process-id process) exit-status)
+ (condition-case err
+ (progn
+ (flymake-log 3 "cleaning up using %s" cleanup-f)
+ (when (buffer-live-p source-buffer)
+ (with-current-buffer source-buffer
+ (funcall cleanup-f)))
+
+ (delete-process process)
+ (setq flymake-processes (delq process flymake-processes))
+
+ (when (buffer-live-p source-buffer)
+ (with-current-buffer source-buffer
+
+ (flymake-parse-residual)
+ ;;(flymake-post-syntax-check exit-status command)
+ (flymake-post-syntax-check 0 command)
+ (setq flymake-is-running nil))))
+ (error
+ (let ((err-str (format "Error in process sentinel for buffer %s: %s"
+ source-buffer (error-message-string err))))
+ (flymake-log 0 err-str)
+ (with-current-buffer source-buffer
+ (setq flymake-is-running nil))))))))
+
+
+ ;; 4. redefine this fn - the reason is to allow exit without query on
+ ;; flymake processes. Not sure why this is not the default.
+ (defun flymake-start-syntax-check-process (cmd args dir)
+ "Start syntax check process."
+ (let* ((process nil))
+ (condition-case err
+ (progn
+ (when dir
+ (let ((default-directory dir))
+ (flymake-log 3 "starting process on dir %s"
default-directory)))
+ (setq process (apply 'start-process "flymake-proc"
(current-buffer) cmd args))
+
+ ;; dino - exit without query on active flymake processes
+ (set-process-query-on-exit-flag process nil)
+
+ (set-process-sentinel process 'flymake-process-sentinel)
+ (set-process-filter process 'flymake-process-filter)
+ (push process flymake-processes)
+
+ (setq flymake-is-running t)
+ (setq flymake-last-change-time nil)
+ (setq flymake-check-start-time (flymake-float-time))
+
+ (flymake-report-status nil "*")
+ (flymake-log 2 "started process %d, command=%s, dir=%s"
+ (process-id process) (process-command process)
+ default-directory)
+ process)
+ (error
+ (let* ((err-str (format "Failed to launch syntax check process '%s'
with args %s: %s"
+ cmd args (error-message-string err)))
+ (source-file-name buffer-file-name)
+ (cleanup-f (flymake-get-cleanup-function
source-file-name)))
+ (flymake-log 0 err-str)
+ (funcall cleanup-f)
+ (flymake-report-fatal-status "PROCERR" err-str))))))
+
+
+ ;; 5. define some advice for the error parsing
+ (defadvice flymake-parse-err-lines (before
+ csharp-flymake-parse-line-patch-1
+ activate compile)
+ (if (string-match "\\.[Cc][Ss]$" (file-relative-name buffer-file-name))
+ ;; clear the auxiliary line information list, when a new parse
+ ;; starts.
+ (setq csharp-flymake-aux-error-info nil)))
+
+ (defadvice flymake-parse-line (around
+ csharp-flymake-parse-line-patch-2
+ activate compile)
+ ;; This advice will run in all buffers. Let's may sure we
+ ;; actually execute the important stiff only when a C# buffer is active.
+ (if (string-match "\\.[Cc][Ss]$" (file-relative-name buffer-file-name))
+
+ (let (raw-file-name
+ e-text
+ result
+ (pattern (list csharp-flymake-csc-error-pattern 1 2 3 4))
+ (line-no 0)
+ (col-no 0)
+ (err-type "e"))
+ (if (string-match (car pattern) line)
+ (let* ((file-idx (nth 1 pattern))
+ (line-idx (nth 2 pattern))
+ (col-idx (nth 3 pattern))
+ (e-idx (nth 4 pattern)))
+ (flymake-log 3 "parse line: fx=%s lx=%s ex=%s"
+ file-idx line-idx e-idx)
+ (setq raw-file-name (if file-idx (match-string file-idx line)
nil))
+ (setq line-no (if line-idx (string-to-number
(match-string line-idx line)) 0))
+ (setq col-no (if col-idx (string-to-number
(match-string col-idx line)) 0))
+ (setq e-text (if e-idx
+ (match-string e-idx line)
+ (flymake-patch-e-text (substring line
(match-end 0)))))
+ (or e-text (setq e-text "<no error text>"))
+ (if (and e-text (string-match "^[wW]arning" e-text))
+ (setq err-type "w"))
+ (flymake-log 3 "parse line: fx=%s/%s lin=%s/%s col=%s/%s
text=%s"
+ file-idx raw-file-name
+ line-idx line-no
+ col-idx (prin1-to-string col-no)
+ e-text)
+
+ ;; add one entry to the list of auxiliary error information.
+ (add-to-list 'csharp-flymake-aux-error-info
+ (list line-no col-no))
+
+ (setq ad-return-value
+ (flymake-ler-make-ler raw-file-name line-no err-type
e-text nil))
+ )))
+
+ ;; else - not in a C# buffer
+ ad-do-it))
+
+
+ ;; 6. finally, define some advice for the line navigation. It moves
+ ;; to the proper column, given the line number containing the
+ ;; error. It first calls the normal `flymake-goto-line', and assumes
+ ;; that the result is that the cursor is on the line that contains the
+ ;; error. At exit from that fn, the column is not important. This advice
+ ;; sets the column.
+ (defadvice flymake-goto-line (around
+ csharp-flymake-goto-line-patch
+ activate compile)
+ ;; This advice will run in all buffers. Let's may sure we
+ ;; actually execute the important stuff only when a C# buffer is active.
+ ad-do-it
+ (if (string-match "\\.[Cc][Ss]$" (file-relative-name buffer-file-name))
+ (let* ((lno (ad-get-arg 0))
+ (epair (assoc lno csharp-flymake-aux-error-info)))
+ (if epair
+ (forward-char (- (cadr epair) (current-column) 1))))))
+
+
+ ;; 7. finally, set the flag
+ (setq csharp--flymake-has-been-installed t))))
+
+
+
+;; ++++++++++++++++++++++
+
+
+
+
+;; Need to temporarily turn off flymake while reverting.
+;; There' some kind of race-condition where flymake is trying
+;; to compile while the buffer is being changed, and that
+;; causes flymake to choke.
+(defadvice revert-buffer (around
+ csharp-advise-revert-buffer
+ activate compile)
+ (let ((is-flymake-enabled
+ (and (fboundp 'flymake-mode)
+ flymake-mode)))
+ ;; disable
+ (if is-flymake-enabled
+ (flymake-mode-off))
+
+ ;; revert
+ ad-do-it
+
+ ;; enable
+ (if is-flymake-enabled
+ (flymake-mode-on))))
+
+
+
+
+ ;; ==================================================================
+ ;; C# code-doc insertion magic
+ ;; ==================================================================
+ ;;
+ ;; In Visual Studio, if you type three slashes, it immediately expands into
+ ;; an inline code-documentation fragment. The following method does the
+ ;; same thing.
+ ;;
+ ;; This is the kind of thing that could be handled by YASnippet or
+ ;; another similarly flexible snippet framework. But I don't want to
+ ;; introduce a dependency on yasnippet to csharp-mode. So the capability
+ ;; must live within csharp-mode itself.
+
+ (defun csharp-maybe-insert-codedoc (arg)
+
+ "Insert an xml code documentation template as appropriate, when
+typing slashes. This fn gets bound to / (the slash key), in
+csharp-mode. If the slash being inserted is not the third
+consecutive slash, the slash is inserted as normal. If it is the
+third consecutive slash, then a xml code documentation template
+may be inserted in some cases. For example,
+
+ a <summary> template is inserted if the prior line is empty,
+ or contains only an open curly brace;
+ a <remarks> template is inserted if the prior word
+ closes the <summary> element;
+ a <returns> template is inserted if the prior word
+ closes the <remarks> element;
+ an <example> template is inserted if the prior word closes
+ the <returns> element;
+ a <para> template is inserted if the prior word closes
+ a <para> element.
+
+In all other cases the slash is inserted as normal.
+
+If you want the default cc-mode behavior, which implies no automatic
+insertion of xml code documentation templates, then use this in
+your `csharp-mode-hook' function:
+
+ (local-set-key (kbd \"/\") 'c-electric-slash)
+
+ "
+ (interactive "*p")
+ ;;(message "csharp-maybe-insert-codedoc")
+ (let (
+ (cur-point (point))
+ (char last-command-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))
+
+ ;; set the flag, that we actually inserted text
+ (setq did-auto-insert t)
+
+ ;; save point of beginning of insertion
+ (setq cur-point (point))
+
+ ;; actually insert the text
+ (insert text-to-insert)
+
+ ;; indent the inserted string, and re-position point,
either through
+ ;; the case-specific fn, or via the default progn.
+ (if fn-to-call
+ (funcall fn-to-call)
+
+ (let ((newline-count 0) (pos 0) ix)
+
+ ;; count the number of newlines in the inserted
string
+ (while (string-match "\n" text-to-insert pos)
+ (setq pos (match-end 0)
+ newline-count (+ newline-count 1) )
+ )
+
+ ;; indent what we just inserted
+ (c-indent-region cur-point (point) t)
+
+ ;; move up n/2 lines. This assumes that the
+ ;; inserted text is ~symmetric about the halfway
point.
+ ;; The assumption holds if the xml code doc uses a
+ ;; begin-elt and end-elt on a new line all by
themselves,
+ ;; and a blank line in between them where the
point should be.
+ ;; A more intelligent implementation would use a
specific
+ ;; marker string, like @@DOT, to note the desired
point.
+ (forward-line (- 0 (/ newline-count 2)))
+ (end-of-line)))))))))
+
+ (if (not did-auto-insert)
+ (self-insert-command (prefix-numeric-value arg)))))
+
+ ;; ==================================================================
+ ;; end of c# code-doc insertion magic
+ ;; ==================================================================
+
+
+
+
+ ;; ==================================================================
+ ;; c# fontification extensions
+ ;; ==================================================================
+ ;; Commentary:
+ ;;
+ ;; The purpose of the following code is to fix font-lock for C#,
+ ;; specifically for the verbatim-literal strings. C# is a cc-mode
+ ;; language and strings are handled mostly like other c-based
+ ;; languages. The one exception is the verbatim-literal string, which
+ ;; uses the syntax @"...".
+ ;;
+ ;; `parse-partial-sexp' treats those strings as just regular strings,
+ ;; with the @ a non-string character. This is fine, except when the
+ ;; verblit string ends in a slash, in which case, font-lock breaks from
+ ;; that point onward in the buffer.
+ ;;
+ ;; This is an attempt to fix that.
+ ;;
+ ;; The idea is to scan the buffer in full for verblit strings, and apply the
+ ;; appropriate syntax-table text properties for verblit strings. Also setting
+ ;; `parse-sexp-lookup-properties' to t tells `parse-partial-sexp'
+ ;; to use the syntax-table text properties set up by the scan as it does
+ ;; its parse.
+ ;;
+ ;; Also need to re-scan after any changes in the buffer, but on a more
+ ;; limited region.
+ ;;
+
+
+ ;; ;; I don't remember what this is supposed to do,
+ ;; ;; or how I figured out the value.
+ ;; ;;
+ ;; (defconst csharp-font-lock-syntactic-keywords
+ ;; '(("\\(@\\)\\(\"\\)[^\"]*\\(\"\\)\\(\"\\)[^\"]*\\(\"\\)[^\"]"
+ ;; (1 '(6)) (2 '(7)) (3 '(1)) (4 '(1)) (5 '(7))
+ ;; ))
+ ;; "Highlighting of verbatim literal strings. See also the variable
+ ;; `font-lock-keywords'.")
+
+
+
+ (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.
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" msg))
- t))
+ (if (<= level csharp-log-level)
+ (let* ((msg (apply 'format text args)))
+ (message "C# %s %s" (cscomp-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-in-literal (&optional lim detect-cpp)
- "Return the type of literal point is in, if any.
-Basically this works like `c-in-literal' except it doesn't
-use or fill the cache (`c-in-literal-cache').
-The return value is `c' if in a C-style comment, `c++' if in a C++
-style comment, `string' if in a string literal, `pound' if DETECT-CPP
-is non-nil and in a preprocessor line, or nil if somewhere else.
-Optional LIM is used as the backward limit of the search. If omitted,
-or nil, `c-beginning-of-syntax' is used.
-Note that this function might do hidden buffer changes. See the
-comment at the start of cc-engine.el for more info."
- (let ((rtn
- (save-excursion
- (let* ((pos (point))
- (lim (or lim (progn
- (c-beginning-of-syntax)
- (point))))
- (state (parse-partial-sexp lim pos)))
- (csharp-log 4 "parse lim(%d) state: %s" lim (prin1-to-string
state))
- (cond
- ((elt state 3)
- (csharp-log 4 "in literal string (%d)" pos)
- 'string)
- ((elt state 4)
- (csharp-log 4 "in literal comment (%d)" pos)
- (if (elt state 7) 'c++ 'c))
- ((and detect-cpp (c-beginning-of-macro lim)) 'pound)
- (t nil))))))
- rtn))
-
-
-(defun csharp-set-vliteral-syntax-table-properties (beg end)
- "Scan the buffer text between BEG and END, a verbatim literal
+ (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.
@@ -1965,72 +2812,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
- ;; 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
+ ((= 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)))
- ;; everything else
- (t
- ;;(message (format "set-s-t: none pos(%d) chr(%c)" curpos
(char-after curpos)))
- nil))))
- ;; next char
- (setq curpos (+ curpos 1))))))
-
-
+ ((= 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)))
-(defun csharp-end-of-verbatim-literal-string (&optional lim)
- "Moves to and returns the position of the end quote of the verbatim literal
+ ((= 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
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.
@@ -2038,38 +2885,38 @@ 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)
+ (defun csharp-scan-for-verbatim-literals-and-set-props (&optional beg end)
-"Scans the buffer, between BEG and END, for verbatim literal
+ "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.
@@ -2092,135 +2939,135 @@ buffer. Otherwise it is the last cursor position
examined by the
scan.
"
- (if (not (c-major-mode-is 'csharp-mode)) ;; don't scan if not csharp mode
- nil
- (save-excursion
- (c-save-buffer-state
- ((curpos (or beg (point-min)))
- (lastpos (or end (point-max)))
- (state 0) (start 0) (cycle 0)
- literal eos limits)
-
- (csharp-log 3 "scan")
- (goto-char curpos)
-
- (while (and (< curpos lastpos) (< cycle 10000))
- (cond
-
- ;; Case 1: current char is a @ sign
- ;; --------------------------------------------
- ;; Check to see if it demarks the beginning of a verblit
- ;; string.
- ((= ?@ (char-after curpos))
+ (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)
- ;; 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.
+ (csharp-log 3 "scan")
+ (goto-char curpos)
- ;; 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))
+ (while (and (< curpos lastpos) (< cycle 10000))
(cond
- ;; Case 1.A: it's a @ within a string.
+ ;; Case 1: current char is a @ sign
;; --------------------------------------------
- ;; 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)))))
+ ;; 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)))))
- ;; 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
+ ;; 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 2.A: a quote within a string
- ;; --------------------------------------------
- ;; This shouldn't happen, because we hop over strings.
- ;; But it might.
- ((eq literal 'string) nil)
+ (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.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))))
+ (csharp-log 4 "scan: jump end verblit string (%d)" eos)
+ (setq curpos eos))))
- ;; Case 2.C: Not in a comment, and not in a string.
+ ;; Case 2: current char is a double-quote.
;; --------------------------------------------
- ;; 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))))))))
+ ;; 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))))
+
+
+ ;; 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'.
@@ -2244,36 +3091,33 @@ The return value is meaningless, and is ignored by
cc-mode.
-(c-lang-defconst c-before-font-lock-function
- csharp 'csharp-before-font-lock)
-
-;; ==================================================================
-;; end of c# fontification extensions
-;; ==================================================================
-
+ (c-lang-defconst c-before-font-lock-function
+ csharp 'csharp-before-font-lock)
+ ;; ==================================================================
+ ;; end of c# fontification extensions
+ ;; ==================================================================
-;; ==================================================================
-;; C#-specific optimizations of cc-mode funcs
-;; ==================================================================
-
-;; There's never a need to 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)
- )
+ ;; ==================================================================
+ ;; C#-specific optimizations of cc-mode funcs
+ ;; ==================================================================
-;; ==================================================================
-;; end of 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)
+ )
+ ;; ==================================================================
+ ;; end of C#-specific optimizations of cc-mode funcs
+ ;; ==================================================================
@@ -2281,185 +3125,186 @@ The return value is meaningless, and is ignored by
cc-mode.
-;; ==================================================================
-;; 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.
+ ;; ==================================================================
+ ;; c# - monkey-patching of basic parsing logic
+ ;; ==================================================================
;;
- ;; 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.
+ ;; 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.
;;
- ;; 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
+ (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
- (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)
+ (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 ((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))
@@ -2557,113 +3402,172 @@ The return value is meaningless, and is ignored by
cc-mode.
(c-most-enclosing-brace paren-state))
(setq bufpos (point))))
)
- bufpos))
- ))
+ 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 . +)
+ ))
+ ))
+
+
+
+(defun csharp-guess-compile-command ()
+ "set `compile-command' intelligently depending on the
+current buffer, or the contents of the current directory.
+"
+ (interactive)
+ (set (make-local-variable 'compile-command)
+
+ (cond
+ ((or (file-expand-wildcards "*.csproj" t)
+ (file-expand-wildcards "*.vcproj" t)
+ (file-expand-wildcards "*.vbproj" t)
+ (file-expand-wildcards "*.shfbproj" t)
+ (file-expand-wildcards "*.sln" t))
+ (concat csharp-msbuild-tool " "))
+
+ ;; sometimes, not sure why, the buffer-file-name is
+ ;; not set. Can use it only if set.
+ (buffer-file-name
+ (let ((filename (file-name-nondirectory buffer-file-name)))
+ (cond
+
+ ;; editing a c# file - check for an explicitly-specified command
+ ((string-equal (substring buffer-file-name -3) ".cs")
+ (let ((explicitly-specified-command
+ (csharp-get-value-from-comments "compile"
csharp-cmd-line-limit)))
+
+
+ (if explicitly-specified-command
+ (csharp-replace-command-tokens explicitly-specified-command)
+ (concat csharp-make-tool " " ;; assume a makefile exists
+ (file-name-sans-extension filename)
+ ".exe"))))
+
+ ;; something else - do a typical .exe build
+ (t
+ (concat csharp-make-tool " "
+ (file-name-sans-extension filename)
+ ".exe")))))
+ (t
+ ;; punt
+ (concat csharp-make-tool " ")))))
+
+
+
+(defun csharp-invoke-compile-interactively ()
+ "fn to wrap the `compile' function. This simply
+checks to see if `compile-command' has been previously set, and
+if not, invokes `csharp-guess-compile-command' to set the value.
+Then it invokes the `compile' function, interactively.
+
+The effect is to guess the compile command only once, per buffer.
+
+I tried doing this with advice attached to the `compile'
+function, but because of the interactive nature of the fn, it
+didn't work the way I wanted it to. So this fn should be bound to
+the key sequence the user likes for invoking compile, like ctrl-c
+ctrl-e.
+"
+ (interactive)
+ (cond
+ ((not (boundp 'csharp-local-compile-command-has-been-set))
+ (csharp-guess-compile-command)
+ (set (make-local-variable 'csharp-local-compile-command-has-been-set) t)))
+ ;; local compile command has now been set
+ (call-interactively 'compile))
-;; Custom variables
-;;;###autoload
-(defcustom csharp-mode-hook nil
- "*Hook called by `csharp-mode'."
- :type 'hook
- :group 'c)
;;; The entry point into the mode
;;;###autoload
-(defun csharp-mode ()
- "Major mode for editing C# code. This mode is derived from CC Mode to
+ (defun csharp-mode ()
+ "Major mode for editing C# code. This mode is derived from CC Mode to
support C#.
The hook `c-mode-common-hook' is run with no args at mode
@@ -2675,86 +3579,492 @@ respectively, for Csc.exe error and warning messages.
Key bindings:
\\{csharp-mode-map}"
- (interactive)
- (kill-all-local-variables)
- (make-local-variable 'beginning-of-defun-function)
- (make-local-variable 'end-of-defun-function)
- (c-initialize-cc-mode t)
- (set-syntax-table csharp-mode-syntax-table)
-
- ;; define underscore as part of a word in the Csharp syntax table
- (modify-syntax-entry ?_ "w" csharp-mode-syntax-table)
-
- ;; define @ as an expression prefix in Csharp syntax table
- (modify-syntax-entry ?@ "'" csharp-mode-syntax-table)
-
- (setq major-mode 'csharp-mode
- mode-name "C#"
- local-abbrev-table csharp-mode-abbrev-table
- abbrev-mode t)
- (use-local-map csharp-mode-map)
-
- ;; `c-init-language-vars' is a macro that is expanded at compile
- ;; time to a large `setq' with all the language variables and their
- ;; customized values for our language.
- (c-init-language-vars csharp-mode)
-
-
- ;; `c-common-init' initializes most of the components of a CC Mode
- ;; buffer, including setup of the mode menu, font-lock, etc.
- ;; There's also a lower level routine `c-basic-common-init' that
- ;; only makes the necessary initialization to get the syntactic
- ;; analysis and similar things working.
- (c-common-init 'csharp-mode)
-
- ;; csc.exe, the C# Compiler, produces errors like this:
- ;; file.cs(6,18): error CS1006: Name of constructor must match name of class
- (if (boundp 'compilation-error-regexp-alist-alist)
- (progn
- (add-to-list
- 'compilation-error-regexp-alist-alist
- '(ms-csharp "^[
\t]*\\([A-Za-z0-9_][^(]*\\.cs\\)(\\([0-9]+\\)[,]\\([0-9]+\\)) ?:
\\(error\\|warning\\) CS[0-9]+:" 1 2 3))
- (add-to-list
- 'compilation-error-regexp-alist
- 'ms-csharp)))
+ (interactive)
+ (kill-all-local-variables)
+ (make-local-variable 'beginning-of-defun-function)
+ (make-local-variable 'end-of-defun-function)
+ (c-initialize-cc-mode t)
+ (set-syntax-table csharp-mode-syntax-table)
+
+ ;; define underscore as part of a word in the Csharp syntax table
+ (modify-syntax-entry ?_ "w" csharp-mode-syntax-table)
+
+ ;; define @ as an expression prefix in Csharp syntax table
+ (modify-syntax-entry ?@ "'" csharp-mode-syntax-table)
+
+ (setq major-mode 'csharp-mode
+ mode-name "C#"
+ local-abbrev-table csharp-mode-abbrev-table
+ abbrev-mode t)
+ (use-local-map csharp-mode-map)
+
+ ;; `c-init-language-vars' is a macro that is expanded at compile
+ ;; time to a large `setq' with all the language variables and their
+ ;; customized values for our language.
+ (c-init-language-vars csharp-mode)
+
+ ;; `c-common-init' initializes most of the components of a CC Mode
+ ;; buffer, including setup of the mode menu, font-lock, etc.
+ ;; There's also a lower level routine `c-basic-common-init' that
+ ;; only makes the necessary initialization to get the syntactic
+ ;; analysis and similar things working.
+ (c-common-init 'csharp-mode)
+
+ ;; compile
+ (local-set-key "\C-x\C-e" 'csharp-invoke-compile-interactively)
+
+ ;; to allow next-error to work with csc.exe:
+ (setq compilation-scroll-output t)
+
+ ;; csc.exe, the C# Compiler, produces errors like this:
+ ;; file.cs(6,18): error CS1006: Name of constructor must match name of
class
+ (if (boundp 'compilation-error-regexp-alist-alist)
+ (progn
+ (add-to-list
+ 'compilation-error-regexp-alist-alist
+ '(ms-csharp "^[
\t]*\\([-_:A-Za-z0-9][^(]*\\.\\(?:cs\\|xaml\\)\\)(\\([0-9]+\\)[,]\\([0-9]+\\))
?: \\(error\\|warning\\) CS[0-9]+:" 1 2 3))
+ (add-to-list
+ 'compilation-error-regexp-alist
+ 'ms-csharp)))
+
+ ;; flymake
+ (eval-after-load "flymake"
+ '(progn
+ (if csharp-want-flymake-fixup
+ (csharp-flymake-install))))
+
+ (eval-after-load "yasnippet"
+ '(progn
+ (if csharp-want-yasnippet-fixup
+ (csharp-yasnippet-fixup))))
- ;; to allow next-error to work with csc.exe:
- (setq compilation-scroll-output t)
+ (local-set-key (kbd "/") 'csharp-maybe-insert-codedoc)
+ (local-set-key (kbd "{") 'csharp-insert-open-brace)
+ ;; Need the following for parse-partial-sexp to work properly with
+ ;; verbatim literal strings Setting this var to non-nil tells
+ ;; `parse-partial-sexp' to pay attention to the syntax text
+ ;; properties on the text in the buffer. If csharp-mode attaches
+ ;; text syntax to @"..." then, `parse-partial-sexp' will treat those
+ ;; strings accordingly.
+ (set (make-local-variable 'parse-sexp-lookup-properties) t)
- (local-set-key (kbd "/") 'csharp-maybe-insert-codedoc)
- (local-set-key (kbd "{") 'csharp-insert-open-brace)
+ ;; scan the entire buffer for verblit strings
+ (csharp-scan-for-verbatim-literals-and-set-props nil nil)
+ ;; Allow fill-paragraph to work on xml code doc
+ ;; This setting gets overwritten quietly by c-run-mode-hooks,
+ ;; so I put it afterwards to make it stick.
+ (make-local-variable 'paragraph-separate)
- ;; Need the following for parse-partial-sexp to work properly with
- ;; verbatim literal strings Setting this var to non-nil tells
- ;; `parse-partial-sexp' to pay attention to the syntax text
- ;; properties on the text in the buffer. If csharp-mode attaches
- ;; text syntax to @"..." then, `parse-partial-sexp' will treat those
- ;; strings accordingly.
- (set (make-local-variable 'parse-sexp-lookup-properties)
- t)
+ ;;(message "C#: set paragraph-separate")
- ;; scan the entire buffer for verblit strings
- (csharp-scan-for-verbatim-literals-and-set-props nil nil)
+ ;; Speedbar handling
+ (if (fboundp 'speedbar-add-supported-extension)
+ (speedbar-add-supported-extension '(".cs"))) ;; idempotent
- (c-run-mode-hooks 'c-mode-common-hook 'csharp-mode-hook)
+ (c-update-modeline)
+ (c-run-mode-hooks 'c-mode-common-hook 'csharp-mode-hook)
- ;; Allow fill-paragraph to work on xml code doc
- ;; This setting gets overwritten quietly by c-run-mode-hooks,
- ;; so I put it afterwards to make it stick.
- (make-local-variable 'paragraph-separate)
- (setq paragraph-separate
- "[ \t]*\\(//+\\|\\**\\)\\([ \t]+\\|[ \t]+<.+?>\\)$\\|^\f")
+ ;; The paragraph-separate variable was getting stomped by
+ ;; other hooks, so it must reside here.
+ (setq paragraph-separate
+ "[ \t]*\\(//+\\|\\**\\)\\([ \t]+\\|[ \t]+<.+?>\\)$\\|^\f")
- ;;(message "C#: set paragraph-separate")
+ (set (make-local-variable 'comment-auto-fill-only-comments) t)
+ )
+
+
+
+
+ ;; =======================================================
+ ;;
+ ;; This section attempts to workaround an anomalous display behavior
+ ;; for tooltips. It's not strictly necessary, only for aesthetics. The
+ ;; issue is that tooltips can get clipped. This is the topic of Emacs
+ ;; bug #5908, unfixed in v23 and present in v22.
+
+
+ (defadvice tooltip-show (before
+ flymake-for-csharp-fixup-tooltip
+ (arg &optional use-echo-area)
+ activate compile)
+ (progn
+ (if ;;(and (not use-echo-area) (eq major-mode 'csharp-mode))
+ (not use-echo-area)
+ (let ((orig (ad-get-arg 0)))
+ (ad-set-arg 0 (concat " " (cheeso-string-trim
(cheeso-reform-string 74 orig) ?\ )))
+ ))))
+
+
+
+
+;; ========================================================================
+;; YA-snippet integration
+
+(defun csharp-yasnippet-fixup ()
+ "Sets snippets into ya-snippet for C#, if yasnippet is loaded,
+and if the snippets do not already exist.
+"
+ (if (not csharp--yasnippet-has-been-fixed)
+ (if (fboundp 'yas/snippet-table-fetch)
+ ;; yasnippet is present
+ (let ((snippet-table (yas/snippet-table 'csharp-mode))
+ (keymap (if yas/use-menu
+ (yas/menu-keymap-for-mode mode)
+ nil))
+ (yas/require-template-condition nil)
+ (builtin-snips
+ '(
+ ("xmls" "{
+ XmlSerializer s1 = new XmlSerializer(typeof(${1:type}));
+
+ // use this to \"suppress\" the default xsd and xsd-instance namespaces
+ XmlSerializerNamespaces ns = new XmlSerializerNamespaces();
+ ns.Add(\"\", \"\");
+
+ s1.Serialize(new XTWFND(System.Console.Out), object, ns);
+ System.Console.WriteLine(\"\\n\");
+}
+
+ $0
+ /// XmlTextWriterFormattedNoDeclaration
+ /// helper class : eliminates the XML Documentation at the
+ /// start of a XML doc.
+ /// XTWFND = XmlTextWriterFormattedNoDeclaration
+ /// usage: s1.Serialize(new XTWFND(System.Console.Out), thing, ns);
+
+ public class XTWFND : System.Xml.XmlTextWriter
+ {
+ public XTWFND(System.IO.StringWriter w) : base(w) {
Formatting=System.Xml.Formatting.Indented; }
+ public XTWFND(System.IO.TextWriter w) : base(w) { Formatting =
System.Xml.Formatting.Indented; }
+ public XTWFND(System.IO.Stream s) : base(s, null) { Formatting =
System.Xml.Formatting.Indented; }
+ public XTWFND(string filename) : base(filename, null) { Formatting =
System.Xml.Formatting.Indented; }
+ public override void WriteStartDocument() { }
+ }
+
+" "xmlserializer { ... }" nil)
+ ("wl" "System.Console.WriteLine(${0://thing to do});
+" "WriteLine( ... );" nil)
+ ("while" "while (${1:condition})
+{
+ ${0://thing to do}
+}" "while (...) { ... }" nil)
+ ("using" "using (${1:type} ${2:var} = new ${1:type}(${4:ctor args}))
+{
+ ${5:// body...}
+}" "using ... { ... }" nil)
+ ("try" "try
+{
+ $0
+}
+catch (System.Exception exc1)
+{
+ throw new Exception(\"uncaught exception\", exc1);
+}" "try { ... } catch { ... }" nil)
+ ("sum" "/// <summary>
+/// ${1:description}
+/// </summary>
+///
+/// <remarks>
+/// ${2:comments}
+/// </remarks>
+" "/// <summary>..." nil)
+ ("sing" "#region Singleton ${1:className}
+public sealed class $1
+{
+ private readonly static $1 _instance = new $1();
+ public static $1 Instance { get { return _instance; } }
+ static $1() { /* required for lazy init */ }
+ private $1()
+ {
+ // implementation here
+ }
+}
+
+#endregion
+" "public sealed class Singleton {...}" nil)
+ ("setting" " #region Property${1:PropName}
+
+ private string default$1 = ${2:defaultValue};
+ private string _$1;
+ public string $1
+ {
+ get
+ {
+ if (_$1 == null)
+ {
+ _$1 =
System.Configuration.ConfigurationManager.AppSettings[\"$1\"];
+
+ if (string.IsNullOrEmpty(_$1))
+ {
+ _$1 = default$1;
+ }
+ }
+ return this._$1;
+ }
+ set
+ {
+ string new$1 = value;
+ // optional validation:
+ //Validation.EnforceXxxx(new$1, \"$1\");
+ _$1 = new$1;
+ }
+ }
+
+#endregion
+" "config setting" nil)
+ ("prop" "private ${1:Type} _${2:Name};
+public ${1:Type} ${2:Name}
+{
+ get
+ {
+ ${3://get impl}
+ }
+
+ set
+ {
+ ${4://get impl}
+ }
+
+}" "property ... { ... }" nil)
+ ("pa" " for (int i=0; i < args.Length; i++)
+ {
+ switch (args[i])
+ {
+ case \"-?\":
+ case \"-help\":
+ throw new ArgumentException(args[i]);
+
+ default: // positional args
+ if ($2 != 0)
+ // we have all the args we need
+ throw new ArgumentException(args[i]);
+
+ if ($1 == null)
+ $1 = args[i];
+
+ else
+ $2 = System.Int32.Parse(args[i]);
+
+ break;
+ }
+ }
+
+ // check values
+ if ($1 == null)
+ throw new ArgumentException();
+
+ if ($2 == 0)
+ throw new ArgumentException();
+
+
+" "switch(args[0]) {...}" nil)
+ ("openread" " using(Stream src = File.OpenRead($1))
+ {
+ using(Stream dest= File.Create($2))
+ {
+ if (compress)
+ Compress(src, dest);
+ else
+ Decompress(src, dest);
+ }
+ }
+" "File.OpenRead(...)" nil)
+ ("ofd" "var dlg = new System.Windows.Forms.OpenFileDialog();
+dlg.Filter = \"${1:filter string}\"; // ex: \"C# (*.cs)|*.cs|Text
(*.txt)|*.txt\";
+if (dlg.ShowDialog() == DialogResult.OK)
+{
+ string fileName = dlg.FileName;
+ $0
+}
+" "new OpenFileDialog; if (DialogResult.OK) { ... }" nil)
+ ("ife" "if (${1:predicate})
+{
+ ${2:// then clause}
+}
+else
+{
+ ${3:// else clause}
+}" "if (...) { ... } else { ... }" nil)
+ ("fore" "foreach (${1:type} ${2:var} in ${3:IEnumerable})
+{
+ ${4:// body...}
+}" "foreach ... { ... }" nil)
+ ("for" "for (int ${1:index}=0; $1 < ${2:Limit}; $1++)
+{
+ ${3:// body...}
+}" "for (...) { ... }" nil)
+ ("fbd" "using (FolderBrowserDialog dialog = new FolderBrowserDialog())
+{
+ dialog.Description = \"Open a folder which contains the xml output\";
+ dialog.ShowNewFolderButton = false;
+ dialog.RootFolder = Environment.SpecialFolder.MyComputer;
+ if(dialog.ShowDialog() == DialogResult.OK)
+ {
+ string folder = dialog.SelectedPath;
+ foreach (string fileName in Directory.GetFiles(folder, \"*.xml\",
SearchOption.TopDirectoryOnly))
+ {
+ SQLGenerator.GenerateSQLTransactions(Path.GetFullPath(fileName));
+ }
+ }
+}
+
+" "new FolderBrowserDialog; if (DialogResult.OK) { ... }" nil)
+ ("doc" "/// <summary>
+/// ${1:summary}
+/// </summary>
+///
+/// <remarks>
+/// ${2:remarks}
+/// </remarks>
+$0" "XML Documentation" nil)
+ ("conv" " List<String> Values = new List<String>() { \"7\", \"13\", \"41\",
\"3\" };
+
+ // ConvertAll maps the given delegate across all the List elements
+ var foo = Values.ConvertAll((s) => { return System.Convert.ToInt32(s); }) ;
+
+ System.Console.WriteLine(\"typeof(foo) = {0}\", foo.GetType().ToString());
+
+ Array.ForEach(foo.ToArray(),Console.WriteLine);
+" "ConvertAll((s) => { ... });" nil)
+ ("cla" "public class ${1:Classname}
+{
+ // default ctor
+ public ${1:Classname}()
+ {
+ }
+
+ ${2:// methods here}
+}" "class ... { ... }" nil)
+ ("ca" " List<String> Values = new List<String>() { \"7\", \"13\", \"41\",
\"3\" };
+
+ // ConvertAll maps the given delegate across all the List elements
+ var foo = Values.ConvertAll((s) => { return System.Convert.ToInt32(s); }) ;
+
+ System.Console.WriteLine(\"typeof(foo) = {0}\", foo.GetType().ToString());
+
+ Array.ForEach(foo.ToArray(),Console.WriteLine);
+" "ConvertAll((s) => { ... });" nil)
+ ("ass" "
+
+[assembly: AssemblyTitle(\"$1\")]
+[assembly: AssemblyCompany(\"${2:YourCoName}\")]
+[assembly: AssemblyProduct(\"${3}\")]
+[assembly: AssemblyCopyright(\"Copyright � ${4:Someone} 2011\")]
+[assembly: AssemblyTrademark(\"\")]
+[assembly: AssemblyCulture(\"\")]
+[assembly: AssemblyConfiguration(\"\")]
+[assembly: AssemblyDescription(\"${5}\")]
+[assembly: AssemblyVersion(\"${6:1.0.1.0}\")]
+[assembly: AssemblyFileVersion(\"${7:1.0.1.0}\")]
+
+" "assembly info" nil)
+ ("args" "for (int i=0; i < args.Length; i++)
+{
+ switch (args[i])
+ {
+ case \"-f\":
+ i++;
+ if (args.Length <= i) throw new ArgumentException(args[i-1]);
+ _file = args[i];
+ break;
+
+ case \"-p\":
+ i++;
+ if (args.Length <= i) throw new ArgumentException(args[i-1]);
+ _password = args[i];
+ break;
+
+ case \"-d\":
+ i++;
+ if (args.Length <= i) throw new ArgumentException(args[i-1]);
+ _dir = args[i];
+ break;
+
+ case \"-i\":
+ i++;
+ if (args.Length <= i) throw new ArgumentException(args[i-1]);
+ if (_intParam != DefaultIntParamValue)
+ throw new ArgumentException(args[i]);
+ if (args[i].StartsWith(\"0x\"))
+ _intParam = System.Int32.Parse(args[i].Substring(2),
System.Globalization.NumberStyles.AllowHexSpecifier );
+ else
+ _intParam = System.Int32.Parse(args[i]);
+ break;
+
+
+ case \"-s\":
+ i++;
+ if (args.Length <= i) throw new Exception(args[i-1]);
+ if (args[i].ToUpper().EndsWith(\"K\"))
+ _size =
System.Int32.Parse(args[i].Substring(0,args[i].Length-1)) * 1024;
+ else if (args[i].ToUpper().EndsWith(\"KB\"))
+ _size =
System.Int32.Parse(args[i].Substring(0,args[i].Length-2)) * 1024;
+ else if (args[i].ToUpper().EndsWith(\"M\"))
+ _size =
System.Int32.Parse(args[i].Substring(0,args[i].Length-1)) * 1024*1024;
+ else if (args[i].ToUpper().EndsWith(\"MB\"))
+ _size =
System.Int32.Parse(args[i].Substring(0,args[i].Length-2)) * 1024*1024;
+ else
+ _size = Int32.Parse(args[i]);
+ break;
+
+
+
+ case \"-?\":
+ throw new ArgumentException(args[i]);
+
+ default:
+ if (_positionalArg != null)
+ throw new ArgumentException(args[i]);
+
+ _positionalArg = args[i];
+ break;
+ }
+}
+" "switch on args" nil)
+ )))
+
+
+ (setq csharp--yasnippet-has-been-fixed t)
+
+ (add-to-list 'yas/known-modes 'csharp-mode))
+
+ ;; It's possible that Csharp-mode is not on the yasnippet menu
+ ;; Install it here.
+ (when yas/use-menu
+ (define-key
+ yas/menu-keymap
+ (vector 'csharp-mode)
+ `(menu-item "C#" ,keymap)))
+
+ ;; Insert the snippets from above into the table if they
+ ;; are not already defined.
+ (mapcar
+ '(lambda (item)
+ (let* ((full-key (car item))
+ (existing-snip
+ (yas/snippet-table-fetch snippet-table full-key)))
+ (if (not existing-snip)
+ (let* ((key (file-name-sans-extension full-key))
+ (name (caddr item))
+ (condition (nth 3 item))
+ (template (yas/make-template (cadr item)
+ (or name key)
+ condition)))
+ (yas/snippet-table-store snippet-table
+ full-key
+ key
+ template)
+ (when yas/use-menu
+ (define-key keymap (vector (make-symbol full-key))
+ `(menu-item ,(yas/template-name template)
+ ,(yas/make-menu-binding
(yas/template-content template))
+ :keys ,(concat key
yas/trigger-symbol))))))))
+ builtin-snips))))
- ;; Speedbar handling
- (if (fboundp 'speedbar-add-supported-extension)
- (speedbar-add-supported-extension '(".cs"))) ;; idempotent
- (c-update-modeline))
- [elpa] branch externals/csharp-mode created (now dd30649), ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode d700d31 001/459: Initial directory structure., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 084192f 002/459: initial import, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 2a904cb 005/459: First checkin of TFS.el - providing the ability to perform checkin/checkout to MS TFS from within emacs., ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 497a70e 009/459: Simplify csharp-mode; eliminate flymake-for-csharp.el (unnecessary),
ELPA Syncer <=
- [elpa] externals/csharp-mode a6f4b55 012/459: fix doc to remove mention of defunct flymake-for-csharp.el, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 6b688a6 014/459: update makefile, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode fc60bff 019/459: Fix for breakage in Emacs 24.4, ELPA Syncer, 2021/08/22
- [elpa] externals/csharp-mode 13984a8 004/459: First checkin of flymake-for-csharp.el, ELPA Syncer, 2021/08/22
- [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