我修复了此处描述的所有问题(以及另外一个),并在emacswiki上发布了the modified
csharp-mode.el (v0.7.1)
csharp-mode I use 几乎非常好。
它适用于大多数事情,但有一些问题:
#if / #endif标签打破缩进,但仅限于方法范围内。
应用于结构中字段的属性,中断缩进。 (有时,参见示例)
在实现接口的类中,缩进被破坏。从那时起。
文字字符串(以@为前缀)不能正确显示,实际上如果文字字符串中的最后一个字符是斜线,则会在源文件中从该点向前突破fontification。
我认为还有其他一些问题。
我不是模特作家。
有没有人对这种模式有所改进?
有人想自愿修理这些东西吗?
示例代码
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Xml.Serialization;
namespace Cheeso.Says.TreyIsTheBest
{
public class Class1
{
private void Method1()
{
// Problem 1: the following if / endif pair causes indenting to break.
// This occurs only within the scope of a method. If the #if/#endif is
// outside of a method, then the indenting does not break.
#if DIAGS
// this first line of code within the conditional scope
// is indented
String StringNumber1;
// the second line of code within the conditional scope
// is un-indented
public String StringNumber2;
#endif
// The endif is where I expect it to be, I guess.
// It's in-line with the matched #if. But the comments here
// are weirdly indented still further. ??
}
// The prior close-curly is indented 2 units more than I would expect.
}
// the close-curly for the class is indented correctly.
// ==================================================================
// ------------------------------------------------------------------
[StructLayout(LayoutKind.Sequential,
CharSet = CharSet.Unicode)]
public struct Class2
{
// Problem 2: when there is an attribute applied to a field
// within a struct, and the attribute include a newline, then
// the field indents strangely. See also "Note 1", and "Note 2"
// below.
[MarshalAs(UnmanagedType.ByValArray,
SizeConst = 128)]
public int Value1;
// Note 1: this indents fine.
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public int Value2;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class Class3
{
public short PrintNameLength;
[MarshalAs(UnmanagedType.ByValArray,
SizeConst = 128)]
// Note 2: this indents just fine
public int Value1;
}
// ==================================================================
// ------------------------------------------------------------------
// Linq Syntax is not a problem as I had originally thought
public class Class4
{
#region eee
#endregion
private void Method1()
{
var files = Directory.GetFiles("Something");
var selection = from f in files
where System.IO.Path.GetFileName(f).StartsWith("C")
select f;
foreach (var e in selection)
Console.WriteLine(e);
}
}
// ==================================================================
// ------------------------------------------------------------------
public interface IGuess { }
public class Class5 : IGuess
{
// Problem 3: When a #region tag is used inside a class that
// implements an interface (or derives from a class) the line
// following the region tag gets indented one extra unit.
#region utility
private static System.Random rnd= new System.Random();
private string FigureCategory()
{
return "unknown";
}
#endregion
// You can also see artifacts of the same confusion in
// methods that have multiple attributes. Again, this only
// occurs when the containing class implements a particular
// interface or derives from a parent class.
[System.Web.Services.WebMethodAttribute()]
[return: System.Xml.Serialization.XmlElementAttribute("getContainerObjectsReturn")]
public String Method1()
{
return "Hello.";
}
}
// ==================================================================
// ------------------------------------------------------------------
public class Pippo
{
// Problem 4: when the final char in an "escaped" string literal is a
// slash, indenting and fontification breaks.
List<string> directories = new List<string> {
@"C:\Temp\sub1\",
// The emacs parser thinks the string has not ended.
// This comment is fontified and indented as if it is in
// the middle of a string literal.
@"C:\Temp\sub2\",
// Because we have another \" at the end of a string,
// emacs now thinks we're "out" of the string literal.
// This comment is now indented and fontified correctly.
@"C:\Home\"
// A third \", and now emacs thinks we're back inside the string literal.
// The rest of the code will be treated as if it were inside the string literal.
};
protected void Page_Load(object sender, EventArgs e)
{
Console.WriteLine("Hello {0}", "world");
}
}
}
答案 0 :(得分:3)
这段建议似乎解决了缩进问题#1的前半部分。我希望它不会在其他地方引起问题。它只是查找导致错误缩进的条件(语法statement-cont
和#if
或#endif
(嗯,只是#
)))并返回从之前的推断出的语法。对我来说很好,但我不是这里的法官。
(defvar csharp-mode-syntax-table-no-special-slash
(let ((res (copy-syntax-table csharp-mode-syntax-table)))
(modify-syntax-entry ?\\ "w" res)
res)
"same as regular csharp-mode-syntax-table, only \\ is not an escape char")
(defadvice c-guess-basic-syntax (after c-guess-basic-syntax-csharp-hack activate)
"following an #if/#endif, indentation gets screwey, fix it"
(let ((res ad-return-value))
(save-excursion
(save-match-data
(cond ((and (eq major-mode 'csharp-mode)
(eq 'statement-cont (caar res))
(progn
(goto-char (cadar res))
(looking-at "#")))
;; when following a #if, try for a redo
(goto-char (cadar res))
(setq ad-return-value (c-guess-basic-syntax)))
((and (eq major-mode 'csharp-mode)
(eq 'string (caar res)))
;; inside a string
;; check to see if it is a literal
;; and if so, redo with modified syntax table
(let ((p (point))
(extent (c-literal-limits)))
(when extent
(goto-char (- (car extent) 1))
(when (looking-at "@\"")
;; yup, a string literal
(with-syntax-table csharp-mode-syntax-table-no-special-slash
(goto-char p)
(setq ad-return-value (c-guess-basic-syntax))))))))))))
紧密的大括号仍然缩进不正确。我认为维护缩进代码的人会知道如何进行更改。这超出了我的理解范围。由cc引擎管理的缩进有104种不同的“案例”......
(与问题2和3的缩进相同,它们都被认为是'statement-cont语法的一部分)。要查看cc引擎认为当前点下的语法是什么,请执行: C-c C-s 。
关于问题4,文字字符串,上面似乎正确地缩进文字字符串,但是fontification仍然被打破。