打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
VSPaste 的持续改造

VSPaste 的持续改造


Admin
2010年6月20日
Paste from Visual Studio 是一个很好用的代码高亮插件,对于使用Visual Studio编写代码,用WLW写博客的我们来说实在是不二之选。但是作者从2007年11月22日之后就停止了改插件的更新。而到这时,这个插件还有一些不如人意的地方。

很多人都尝试过对这个插件的改造工作(参见《自己改造VSPaste插件》《定制Paste from Visual Studio插件(上)》《定制Paste from Visual Studio插件(下)》),在他们研究的过程中,都由于.NET Reflector无法完成工作而借助了IL。而我在尝试的时候,却发现只是用 .NET Reflector 就完成了对插件源代码的改造工作。以下是具体方法:



用.NET Reflector打开VSPaste.dll文件,选择Export:



导出后就会得到一个C#的项目:


 


然后,用Visual Studio打开这个项目。我的目的是解决以下几个问题:



  1. 当IDE的颜色主题做了修改之后(主要是背景),粘贴时自动将背景颜色设置到<pre>标签而不是<span>标签(一般情况下,背景色的改变都不会是针对关键字而是对整个文本编辑器的);

  2. 如果从代码中间段复制(缩进层次比较多),粘贴时自动将多余的缩进去除。

这两个工作在《自己改造VSPaste插件》中其实都做了,唯一的区别就是DiryBoy是去除背景,而我要保留背景,只是换个地方放置。


第一步,参照DiryBoy的代码直接实现缩进的去除,在VSPaste.cs文件中找到Undent方法,替换其中的源代码:

public static string Undent(string s) {
var beginSpaces = new System.Text.RegularExpressions.Regex("^(?:<span[^>]*>|)( +)");
var depth = beginSpaces.Match(s).Groups[1].Value.Length;
if (depth == 0) return s;

var space2trim = new System.Text.RegularExpressions.Regex
(
"^(<span[^>]*>|) {" + depth + "}"
, System.Text.RegularExpressions.RegexOptions.Multiline
);
var tmp = space2trim.Replace(s, "$1");
var garbageSpan = new System.Text.RegularExpressions.Regex
(
"^<span[^>]*></span>"
, System.Text.RegularExpressions.RegexOptions.Multiline
);
return garbageSpan.Replace(tmp, String.Empty);
}

 



接下来是要将背景设置在<pre>标签中,从源代码里可以发现,<pre>标签的生成是在VSPaste.cs的CreateContent方法中,而背景颜色的判断和设置却不在这里,于是我首先想到的是让具体负责背景颜色的代码将颜色值传递出来,所以对CreateContent的方法我做了这样的修改:

if (Clipboard.ContainsData(DataFormats.Rtf))
{
string allBackColor = string.Empty;
string htmlContent = Undent(HTMLRootProcessor.FromRTF(
(
string)Clipboard.GetData(DataFormats.Rtf),
out allBackColor));
if(string.IsNullOrEmpty(allBackColor)) {
newContent =
string.Format(
"<pre class=\"code\">{0}</pre><p></p>",
htmlContent);
}
else
{
newContent =
string.Format(
"<pre class=\"code\" style=\"background:{0};\">{1}</pre><p></p>",
allBackColor,
htmlContent);
}
return DialogResult.OK;
}

原来的代码是:

if (Clipboard.ContainsData(DataFormats.Rtf))
{
newContent =
"<pre class=\"code\">" + Undent(HTMLRootProcessor.FromRTF((string) Clipboard.GetData(DataFormats.Rtf))) + "</pre><p></p>";
return DialogResult.OK;
}

我的改变就是用为HTMLRootProcessor类的FromRTF方法增加一个传出参数,通过这个参数来获取背景色,从而可以在生成<pre>标签时直接使用。接下来,打开HTMLRootProcessor这个方法,通过阅读其源代码,可以知道,由int类型的颜色转成string类型是通过ColorProcessor的CssColor方法实现的,而每个HTMLRootProcessor方法里面有一个colors的私有字段就是ColorProcessor的实例。所以,我将HTMLRootProcessor的FromRTF方法改造如下:

public static string FromRTF(string rtf, out string allBackColor)
{
string str;
using (StringWriter writer = new StringWriter())
{
using (StringReader reader = new StringReader(rtf))
{
ProcessorStack stack = new ProcessorStack();
HTMLRootProcessor processor = new HTMLRootProcessor(stack, writer);
stack.Push(processor);
Scanner scanner = new Scanner(reader);
new Parser(scanner, stack).Parse();
allBackColor = processor.background.HasValue ? processor.colors.CssColor(processor.background.Value) :
string.Empty;
str = writer.ToString();
}
}
return str;
}

 



其中高亮的代码就是重点,首先我利用HTMLRootProcessor自带的background属性来存储背景色,然后调用colors实例的CssColor方法来为其赋值,如果没有背景色,则返回空字符串。最后一步,就是修改对background属性赋值的语句,使其只需要判断一次即可(整个代码总共就一种背景色,没必要反复赋值了)。这段代码在HTMLRootProcessor的SyncColors方法中,改造后的代码如下:

private void SyncColors(bool bgOnly)
{
int? nullable;
int? nullable2;
if ((this.background != this.nextBackground) || ((((nullable = this.color).GetValueOrDefault() != (nullable2 = this.nextColor).GetValueOrDefault()) || (nullable.HasValue != nullable2.HasValue)) && !bgOnly))
{
if (this.color.HasValue || this.background.HasValue)
{
this.writer.Write("</span>");
}
this.color = this.nextColor;
if(this.background.HasValue == false)
this.background = this.nextBackground;
if (this.color.HasValue || this.background.HasValue)
{
this.writer.Write("<span style=\"");
if (this.color.HasValue)
{
this.writer.Write("color:");
this.writer.Write(this.colors.CssColor(this.color.Value));
}
//if (this.background.HasValue)
//{
// if (this.color.HasValue)
// {
// this.writer.Write(";");
// }
// this.writer.Write("background:");
// this.writer.Write(this.colors.CssColor(this.background.Value));
//}
this.writer.Write("\">");
}
}
}

其中做了两处修改,第一处是在对background赋值前判断其是否已经有值,如果有了,则不再进行赋值操作。第二处是将原来给<span>标签增加背景色的代码注释掉。


至此已经全部改造完毕,然后进行编译,顺利通过。将得到的VSPaste.dll覆盖到C:\Program Files\Windows Live\Writer\Plugins 目录下,启动WLW,随便从Visual Studio中赋值一段代码,粘贴,得到了本文中代码显示的效果。为了确认,打开没有改变颜色主题的Visual Web Developer 2008 Exress,复制一段代码,粘贴到WLW中,得到了没有背景色的代码样式(这里就不演示了)。至此,大功告成。


最后,对编译修改后的源代码做一点补充说明:如果生成配置是Debug,则没有任何问题,改成Release则一旦使用该插件就会造成WLW崩溃。如果要使用Release配置编译,则应该做如下调整:



这是经过我反复调整测试后得出的,关键在于“定义Debug常量”,其它选项都可选可不选。


本人水平有限,虽然通过尝试得出了正确结果,但是对于编译时发生的事情却不知其所以然,也无法解释其原因。望高人指点。


==================================================


修改后的VSPaste.dll下载:vspaste.zip


 


本文首发:http://wukangrui.com/2010/04/04/vspaste-customization-with-net-reflector.html

本文首发自 刀刀博客,博客园同步更新。如需转载,请注明作者及出处。
Tag标签: Visual Studio,.NET Reflector,C#,VSPaste
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
搜狐ajax hacking漏洞详解——XSS worm
Apache Commons-configuration 学习笔记3
react如何渲染包含html标签元素的字符串
数据窗口中鼠标拖曳选择数据栏位
使用 Java 访问 Windows 注册表
数值转大写人民币的类的实现
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服