锐化 Notepad++






4.90/5 (153投票s)
本文介绍了用于Notepad++的CS-Script C#智能感知插件(CSScriptNpp)。
本文介绍了用于Notepad++的CS-Script C#智能感知插件(CSScriptNpp)。CSScriptNpp插件将Notepad++转变为一个轻量级但功能齐全的IDE类环境,用于开发和执行C#代码。
引言
CSScriptNpp旨在通过顶级的“代码辅助”扩展Notepad++,并使用户能够在没有通常与其他IDE相关的部署或许可麻烦的情况下执行“独立”C#代码。
虽然该插件不与任何知名IDE(如Visual Studio、Mono Develop或Eclipse)直接或间接竞争,但它提供了许多在这些成熟IDE中常见的核心功能。
该插件提供了MS Visual Studio风格的用户体验,但并未完全复制。CSScriptNpp永远无法100%匹配Visual Studio的编辑能力,而Visual Studio也永远无法匹配CSScriptNpp的简洁性和高可用性。
CSScriptNpp的高可用性归因于Notepad++插件部署模型。要开始使用CSScriptNpp,您只需在Notepad++插件管理器中激活它。
注意:安装后,您可能需要从“关于”框中检查最新的CSScriptNpp版本。
该插件允许直接从Notepad++执行C#代码(脚本),无需任何基础设施(例如项目文件)。它还提供了便捷的C#脚本启动功能,并可附加系统CLR调试器(例如VS)。
该插件还可用于准备简单的部署包(或可执行文件),以便在未安装任何CSScriptNpp组件(甚至Notepad++)的系统上执行脚本。
以下是所有插件功能的完整列表:
- 智能感知相关功能
- CLR类型成员自动完成
- 添加缺失的'using'
- 显示CLR类型快速信息(当鼠标悬停在类型成员上时)
- 显示方法重载弹出窗口。
- 转到定义 (F12)
- 在源代码中
- 在重建的引用程序集API接口中(包括XML文档)
- 智能缩进
- 格式化C#源代码
- CodeMap - 显示当前.cs文档类成员的面板
- 支持“纯粹”符合ECMA标准的C#语法
- 通过CS-Script指令包含依赖脚本
- 通过自动将命名空间解析为程序集进行隐式程序集引用
- 通过CS-Script指令进行显式程序集引用
- 拦截调试输出
- 拦截控制台输出
- 常规构建/执行错误报告
- 准备脚本部署包,使其可以在Notepad++之外执行。
在本文中,我将只描述插件的主要功能及其实现的技术方面(和挑战)。
致谢
CSScriptNpp插件依赖于许多第三方解决方案,其中有两个值得特别提及:CSharpCode.NRefactory和NppPlugin.NET。这两个出色的框架使CSScriptNpp成为可能。虽然可以使用其他替代解决方案,但如果没有这两个非凡的解决方案,我不会尝试进行如此具有挑战性的开发。
概述
在Windows上进行开发的人很难没听说过Notepad++。许多人认为它是最好的文本编辑器和“必备”的源代码编辑工具。其当之无愧的声誉归功于其巧妙的架构和几乎完美的实现。
Notepad++基于文本渲染引擎Scintilla,该引擎已被许多源代码编辑器使用。除了速度快且功能丰富之外,Scintilla还非常注重源代码编辑任务。Notepad++提供了Scintilla的所有优点,并通过允许多文档编辑以及许多其他功能对其进行了扩展。但可以说Notepad++最吸引人的功能是其可插拔架构。因此,开箱即用的功能可以通过第三方插件实现。
虽然Notepad++功能丰富,但仍有一些空白需要填补。因此,自动完成功能完全不了解上下文。它只不过是一个“常用词”列表,按源代码文档的类型分组。对于解释型语言来说,这可能没问题,但对于C#等编译型语言来说却并非如此。使用Notepad++编辑C#代码的舒适度甚至无法与Visual Studio提供的舒适度相比。而这正是本文介绍的插件CSScriptNpp试图解决的问题。
它不仅提供了真正的上下文特定代码自动完成(如VS Intellisense),还允许方便的代码执行,以及在完整IDE中常见的许多其他功能。
我坚信,尽管Visual Studio提供了几乎无与伦比的代码编辑能力,但仍强烈需要占用空间更小、运行时更轻、许可更宽松的替代工具。
我对Rob Eisenberg为他的Caliburn.Micro所做的非传统动机印象深刻。他说:“我的愿景是提取Caliburn 90%的功能并将其压缩到10%的代码中”。这正是我对CSScriptNpp的感受。虽然在我的案例中,我正在“压缩”Visual Studio的功能。我不认为该插件提供了其中90%的功能。也许只是最常用功能的70%。而付出的努力和代码库大小可能<1%。
Intellisense 相关功能是在 NRefactory 的帮助下实现的,但插件的核心是 CS-Script 执行引擎——这是我的另一个宠物项目。
我一直觉得CS-Script缺少一个功能丰富的专用编辑器,有点不完整。我甚至认真尝试开发一个。我花了不少时间反向工程SharpDevelop,几乎完成了一个C#专用编辑器——一个自定义的基于WinForm的编辑器,封装了pre-version-5的NRefactory。
然而,我不满意它的性能和不够通用的特性。因此我放弃了这个项目,转而专注于将CS-Script与Visual Studio集成(CS-Script VS Tools)。但我总是嫉妒Notepad++的终极可用性、令人印象深刻的性能和极其轻巧的特性。这是我开发这个插件的另一个强烈动机。
CSScriptNpp是CS-Script为Notepad++开发的两个插件之一。第二个是NppScripts——用于通过C#脚本自动化Notepad++的插件。它的开发已经完成(几周内发布),但它是另一篇文章的主题。
插件架构亮点
托管
传统的Notepad++插件开发需要用C++编写代码。虽然我对C++完全熟悉,但我更喜欢C#。因此,我使用了NppPlugin.NET作为插件容器。这个容器是解决Interop挑战的一种相当优雅的方法。它不过是一个特殊的VS项目模板,带有一个非常巧妙的后期构建操作,可以注入特殊的本机导出符号。因此,它使得像Notepad++这样的非托管宿主应用程序可以直接宿主普通的程序集,而无需任何包装器。项目模板还提供了所有Notepad++功能(通常在任何其他插件中可用)的接口(结构、常量等)。
智能感知所有代码分析功能(例如智能感知)都基于ICSharpCode.NRefactory(SharpDevelop IDE的一部分)。可以说,它是目前可用于解析C#代码和构建语法树的最成熟的开源解决方案。它甚至已经开箱即用地实现了代码自动完成功能。然而,现实情况要复杂一些。NRefactory几乎没有任何文档。它的作者提供了一套全面的代码示例,这似乎是一个更好的选择。但是,所有示例都过于SharpDevelop特定,无助于在SharpDevelop UI控件套件之外使用该库。我花了一些时间和精力反向工程API,但最终我成功地将NRefactory与Notepad++插件集成起来。
然而,这并非唯一的挑战。当我第一次尝试C#编辑器(大约4年前)时,我将ICSharpCode.NRefactory.dll封装到一个更易于管理的通用适配器中。在2013年,我试图重用该包装器,但令我失望的是,我意识到我必须从头再来,因为NRefactory API已经完全改变。现在它被称为NRefactory5。
今天,NRefactory5仍有一些功能尚未最终确定,但它非常适合CSScriptNpp的需求。因此,可以实现自动完成(如MS Intellisense)、“转到定义”、“查找所有引用”、“添加缺失的Using”以及所有“显示成员信息”的情况。
CS-Script 集成
脚本执行和依赖管理是使用CS-Script执行引擎实现的。您可以在我的CodeProject文章“C#脚本:缺失的拼图”中找到所有详细信息。简而言之,CS-Script允许执行纯粹的(ECMA兼容的)C#代码,而无需构建可执行文件或维护任何基础设施(如VS项目)。通过CS-Script,还可以直接从脚本代码中表达依赖项(引用的程序集和其他脚本)。请注意,您不需要安装CS-Script,因为插件包含执行脚本所需的最小CS-Script程序集集。
已经熟悉CS-Script,特别是Visual Studio扩展“适用于VS2012-13的CS-Script工具”的开发人员,很可能会发现自己也对CSScriptNpp感到舒适。用户体验非常相似。事实上,CSScriptNpp允许只需单击工具栏按钮即可在Visual Studio中加载脚本。当您的脚本需要Visual Studio的全部功能(例如集成调试器)时,这会很有用。
使用许多插件功能都直截了当且不言自明。您可以在这里找到有关如何使用任何特定功能的详细信息。但最简单的用例如下:
特定功能 这里。但最简单的用例如下
- 通过单击工具栏按钮或选择菜单项插件->CS-Script->项目面板,使项目面板可见
-
创建并加载新脚本
-
修改脚本并使用F7或Ctrl+Shift+B或直接点击验证按钮进行验证
此步骤是可选的。
-
现在您可以使用 F5 执行脚本
执行/跟踪/调试 当执行脚本时,您可以选择将其作为一个完全独立的外部进程(Shift+F5)执行,或者您可以允许CSScriptNpp监听调试输出消息(F5)。这个有趣的功能是基于现有DbMon.Net解决方案实现的,所有功劳都应归于其创建者Christian Birkl。DbMon.Net拦截所有Debug.Write*和Trace.Write*消息,并将它们打印在输出面板中。您还可以使用此功能监听系统上的所有调试消息(类似于SysInternals Dbgview.exe)。
CSScriptNpp还允许拦截控制台输出消息。
不过,如果您的控制台也需要用户输入,那么拦截 StdOut 并不是很实用,因为它会隐藏实际的控制台窗口。
除了捕获调试输出,插件的最新版本还集成了MDbg(微软出品)。
代码导航 代码导航功能包括以下特性:
-
由Notepad++提供的高级文本搜索功能。
-
常规的“查找所有引用”和“转到定义”,其工作方式与Visual Studio中的相同功能非常相似。这还包括引用程序集接口及其XML文档的重建(反编译)。
-
CodeMap - 当前文档类成员列表。Visual Studio中没有等效功能,只能通过VS扩展实现。
此功能在处理大型源代码时特别有用,例如重建(反编译)的引用程序集。
格式化
代码自动格式化是任何现代IDE的必要组成部分。我认为它是CSScriptNpp的必备功能。
我不得不做出一个艰难的决定,实现我自己的解决方案,而不是使用ICSharpCode.NRefactory内置的代码格式化功能。不幸的是,NRefactory格式化功能不完全完善(至少在我使用的版本中),并且不够灵活,无法处理非标准语法(例如无类C#脚本)。因此我开发了一个轻量级的通用代码解析器。
它不是一个真正全面的C#解析器,无论从其可靠性、功能(或优雅性)来看都不是。但它确实起作用。这个简单的括号匹配引擎使得在不修复/扩展ICSharpCode.NRefactory的情况下实现插件功能成为可能。
限制
重要的是要了解插件的局限性。最明显的一点是,智能感知的质量取决于其引擎(ICSharpCode.NRefactory)。我已经在与CSScriptNpp相关的领域中发现了相当多的NRefactory局限性。在等待NRefactory更新带来改进的同时,我实现了一些变通方案。然而,最近的NRefactory更新并没有带来任何改进,反而破坏了已经正常工作的功能。因此我不得不忽略该更新。不幸的是,NRefactory处于永久“变动”中,其API也相当“不稳定”,因此,除非有非常充分的理由,我计划不迁移到新版本的NRefactory。
CSScriptNpp旨在用于小型到中等规模的脚本应用程序。对于大型产品,特别是那些基于异构源内容(资源、XAML、T4等)的产品,它不太可能同样有效。
在第一个版本中,停靠窗口的初始位置处理不准确。这导致CSScriptNpp面板在首次加载时需要手动停靠。之后,它们的正确停靠将由Notepad++正确保留和维护。
关注点
作为插件开发的一部分,我还完成了几个具有独特功能的微型项目。
Reflector - 程序集反编译解决方案,将程序集接口重建为C#代码。Visual Studio也能做到这一点,但我认为CSScriptNpp做得稍微好一些。
代码格式化 - 尽管不理想,但它在功能和实用性之间取得了良好的平衡。
调试监视器 - 经济实惠但功能非常强大且可重用的解决方案。
键盘拦截 - 用于应用程序范围按键监控的简单可重用解决方案。它允许Notepad++和CSScriptNpp重叠的快捷键(例如F5)在没有任何冲突的情况下进行处理。自动更新 - Notepad++插件管理器是向用户提供产品的绝佳工具。然而,它的发布周期(一到两个月)不利于快速响应的产品支持。因此,我开发了从“关于”框检查和应用更新的功能。更新来源于CS-Script服务器,并以MSI形式实现。有趣的是,MSI更新是用Wix#(我的另一个专利项目)编写的。
无类脚本 - CS-Script一直支持无类脚本 - 没有类定义的独立C#代码。但没有编辑工具(包括VS)可以完全支持此类代码。只有Notepad++为普通C#和无类C#提供相同的支持级别。事实上,当我开始使用CSScriptNpp时,无类格式成为了我的默认选择。
注意:无类格式允许可选地将“Main”替换为“main”:
//css_args /ac
using System;
void main(string[] args)
{
Console.WriteLine("Hello World!");
}
结论
CSScriptNpp的开发有几个原因。我希望Notepad++能配备一流的自动完成功能(与MS Intellisense相当)。我希望CS-Script能有一个一流的专用编辑器,能够充分发挥脚本引擎的潜力。
但我还有另一个不那么明显但非常强烈的动机......
我们都被日常工作的复杂挑战所困扰。框架、工厂、模式、设计原则……我们几乎忘记了编程的乐趣。我见过许多CodeProject解决方案,用于批量重命名工具、下载器、目录同步器或另一个MP3文件标签组织器。这类实用程序通常会吸引全面的应用程序开发(甚至部署解决方案),但在许多情况下,只需几行高级语言代码即可实现相同的结果(请参阅示例部分)。而CSScriptNpp插件允许在Notepad++中执行此类代码。它还允许准备脚本,以便在未安装Notepad++的PC上运行它们。
我认为Notepad++与CS-Script为我们提供了一个很好的机会,让我们坐下来,只管编码。编码时无需担心任何代码基础设施。编码时无需考虑将项目文件保存在何处,也无需考虑在哪里找到刚刚编译的可执行文件。只为纯粹的乐趣而编码。
示例
以下示例并非描述 C# 脚本本身。它们只是让您了解现在可以直接从 Notepad++ 执行的 C# 代码类型。
这个小脚本允许将MP3文件的音轨和名称标签嵌入到当前目录中所有文件的文件名中。
//css_args /ac
//css_ref lib\taglib-sharp.dll
using System.IO;
using System;
void main()
{
foreach(string file in Directory.GetFiles(".", "*.mp3"))
{
var mp3 = TagLib.File.Create(file);
string fileName = string.Format("{00}.{1}.mp3", mp3.Tag.Track, mp3.Tag.Title);
string dir = Path.GetDirectoryName(file);
File.Move(file, Path.Combine(dir, fileName));
}
Console.WriteLine("Done...");
}
此脚本演示了.NET 4.5的Async功能的使用
//css_args /ac
using System.Threading;
using System.Threading.Tasks;
using System;
void main(string[] args)
{
Execute();
Console.ReadLine();
}
async void Execute()
{
await Task.Run(()=>
{
Thread.Sleep(1000);
Console.WriteLine("Continue");
});
Console.WriteLine("Done");
}