65.9K
CodeProject 正在变化。 阅读更多。
Home

锐化 Notepad++

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (153投票s)

2013 年 12 月 9 日

MIT

13分钟阅读

viewsIcon

136875

downloadIcon

321

本文介绍了用于Notepad++的CS-Script C#智能感知插件(CSScriptNpp)。

本文介绍了用于Notepad++的CS-Script C#智能感知插件(CSScriptNpp)。CSScriptNpp插件将Notepad++转变为一个轻量级但功能齐全的IDE类环境,用于开发和执行C#代码。

引言

CSScriptNpp旨在通过顶级的“代码辅助”扩展Notepad++,并使用户能够在没有通常与其他IDE相关的部署或许可麻烦的情况下执行“独立”C#代码。

虽然该插件不与任何知名IDE(如Visual StudioMono DevelopEclipse)直接或间接竞争,但它提供了许多在这些成熟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.NRefactoryNppPlugin.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-ScriptVisual Studio集成(CS-Script VS Tools)。但我总是嫉妒Notepad++的终极可用性、令人印象深刻的性能和极其轻巧的特性。这是我开发这个插件的另一个强烈动机。

CSScriptNppCS-ScriptNotepad++开发的两个插件之一。第二个是NppScripts——用于通过C#脚本自动化Notepad++的插件。它的开发已经完成(几周内发布),但它是另一篇文章的主题。

插件架构亮点

托管
传统的Notepad++插件开发需要用C++编写代码。虽然我对C++完全熟悉,但我更喜欢C#。因此,我使用了NppPlugin.NET作为插件容器。这个容器是解决Interop挑战的一种相当优雅的方法。它不过是一个特殊的VS项目模板,带有一个非常巧妙的后期构建操作,可以注入特殊的本机导出符号。因此,它使得像Notepad++这样的非托管宿主应用程序可以直接宿主普通的程序集,而无需任何包装器。项目模板还提供了所有Notepad++功能(通常在任何其他插件中可用)的接口(结构、常量等)。

智能感知所有代码分析功能(例如智能感知)都基于ICSharpCode.NRefactorySharpDevelop IDE的一部分)。可以说,它是目前可用于解析C#代码和构建语法树的最成熟的开源解决方案。它甚至已经开箱即用地实现了代码自动完成功能。然而,现实情况要复杂一些。NRefactory几乎没有任何文档。它的作者提供了一套全面的代码示例,这似乎是一个更好的选择。但是,所有示例都过于SharpDevelop特定,无助于在SharpDevelop UI控件套件之外使用该库。我花了一些时间和精力反向工程API,但最终我成功地将NRefactoryNotepad++插件集成起来。

然而,这并非唯一的挑战。当我第一次尝试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"); 
}  
© . All rights reserved.