为VS2010编写IDE宏

网上有不少好书,可惜其中有很多是扫描版的,摘抄加注起来很麻烦。为方便自己,也为造福大众,我会将自己喜爱的整理一遍,转换成文本版。

网上有现成的工具,可以将图片版的pdf转换成文本,保存到ms word中。如果源图片足够清晰的话,文本的识别率还是很高的。

不过对于代码,其格式则往往比较混乱。手工在word中进行修正,麻烦不说,还容易出错。想起曾经有过几次在VS2010中整理代码,进行的操作基本上都是查找替换和格式化等等;并且,从vs中拷贝的代码,在word中还可以保留语法高亮(关键字蓝色,字符串暗红色,注释绿色)。(不足的是,从VS2010中拷贝的中文,在word中显示为乱码;而从VS2008中拷贝,则完全正常,并且语法高亮也仍然有效)

查找替换和格式化都是些重复性的劳动,因此想着法子让电脑去做。

一开始打算使用dos批处理,但这样一来如果仍要使用语法高亮,就要手工拷贝到VS2010,在拷贝到word,多了一个步骤,麻烦。于是就想能不能直接在VS2010中完成。没想到还真行。通过网络和MSDN,知道VS提供了一个叫做IDE宏的东西。

IDE宏原理上和VBA差不多,或者说就是应用于VS的VBA,只不过使用的VB变成.Net版的了(我不懂VB,如果说错了勿怪)。

下面说说编写IDE宏的具体步骤(VS2010):

按ALT+F11或者点击菜单:工具-》宏-》宏IDE,出现一个和VS类似的IDE窗口:

在MyMacros上右键添加模块,模块名称随便起(我的如上图所示,叫TieWen,是本人的网名)。

双击模块名称,打开编辑窗口,默认的内容如下:

Imports System
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics

Public Module aaa


End Module




我们所要作的,就是在Module TieWen和End Module之间写入合适的Sub(过程,无返回值)(能否写成Function(有返回值)本人并未深入研究)。

我最近正在整理的书籍中源码是基于Java的,因此给Sub取名为Macro_FormatJava,完整的代码如下(有点问题,多多包涵):

Imports System
Imports System.Collections.Generic
Imports EnvDTE
Imports EnvDTE80
Imports EnvDTE90
Imports EnvDTE90a
Imports EnvDTE100
Imports System.Diagnostics

Public Module TieWen

    Sub MergeAll(ByRef Content As String, ByVal From As String, ByVal sTo As String)
        While (Content.Contains(From))
            Content = Content.Replace(From, sTo)
        End While
    End Sub

    Sub PrefixLf(ByRef Content As String, ByVal Who As String)
        Content = Content.Replace(Who, vbLf + Who)
    End Sub

    Sub PostfixLf(ByRef Content As String, ByVal Who As String)
        Content = Content.Replace(Who, Who + vbLf)
    End Sub

    Sub DTEReplaceAll(ByVal Target As EnvDTE.vsFindTarget, ByVal From As String, ByVal sTo As String, Optional ByVal UseRegEx As Boolean = False, Optional ByVal bLoop As Boolean = True)

        DTE.Find.FindWhat = From
        DTE.Find.ReplaceWith = sTo
        DTE.Find.Target = Target
        DTE.Find.MatchCase = True
        DTE.Find.MatchWholeWord = False
        DTE.Find.MatchInHiddenText = False
        If (UseRegEx) Then
            DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxRegExpr
        Else
            DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
        End If
        DTE.Find.ResultsLocation = vsFindResultsLocation.vsFindResultsNone
        DTE.Find.Action = vsFindAction.vsFindActionReplaceAll
        While ((DTE.Find.Execute() <> vsFindResult.vsFindResultNotFound) And bLoop)

        End While

    End Sub
    ' 以上几个是辅助Sub,而不是宏


    Sub Macro_FormatJava()
        DTE.ActiveDocument.Selection.SelectAll()
        Dim Content As String
        Content = DTE.ActiveDocument.Selection.Text


        '处理开始
        Dim operators_NeedPrefixAndPostfixSpace(), operators_IfIsAssignmentNeedPrefixAndPostfixSpace(), operators_NeedPrefixSpace(), operators_NeedPostfixSpace(), operators_NeedNoSpace(), operators_IfMatchedThenNeedPrefixAndPostfixSpace()
        '此处无法使用VB的Array函数
        operators_NeedPrefixAndPostfixSpace = "public,class,interface,implements,return,:,+,-,*,/,%,&,|,^,<<,>>,=,==,!=,<,<=,>,>=,&&,||".Split(",")
        operators_IfIsAssignmentNeedPrefixAndPostfixSpace = "+,-,*,/,%,&,|,^,<<,>>".Split(",")
        operators_NeedPrefixSpace = "{,!,~".Split(",")
        operators_NeedPostfixSpace = ",|;".Split("|")
        operators_NeedNoSpace = "},->,::,.".Split(",") '不考虑case标签或其它符号后紧跟::的情形
        operators_IfMatchedThenNeedPrefixAndPostfixSpace = "new,delete".Split(",")
        '尚未处理的符号:++、--(前后缀形式的区分比较麻烦)、()、[]、?:
        '一元操作符+、-、*、&被当作二元操作符处理了;
        For Each i In operators_NeedPrefixAndPostfixSpace
            Content = Content.Replace(i, " " + i + " ")
        Next

        For Each i In operators_NeedPrefixSpace
            Content = Content.Replace(i, " " + i)
        Next

        For Each i In operators_NeedPostfixSpace
            Content = Content.Replace(i, i + " ")
        Next

        Content = Content.Replace(vbTab, " ")
        '去除多余的空格
        MergeAll(Content, "  ", " ")

        '合并被分开的//、/*、*/、**,必须在去除多余的空格之后调用
        MergeAll(Content, "/ /", "//")
        MergeAll(Content, "/ *", "/*")
        MergeAll(Content, "* /", "*/")
        MergeAll(Content, "* *", "**")

        '必须在去除多余的空格之后调用
        For Each i In operators_IfIsAssignmentNeedPrefixAndPostfixSpace
            Content = Content.Replace(i + " =", i + "=")
        Next

        '必须在去除多余的空格之后调用
        For Each i In operators_NeedPrefixSpace
            Content = Content.Replace(i + " ", i)
        Next
        For Each i In operators_NeedPostfixSpace
            Content = Content.Replace(" " + i, i)
        Next

        '必须在去除多余的空格之后调用
        For Each i In operators_NeedNoSpace
            Content = Content.Replace(" " + i, i)
            Content = Content.Replace(i + " ", i)
        Next

        'operators_IfMatchedThenNeedPrefixAndPostfixSpace无需处理

        Dim operators_NeedPrefixLf(), operators_NeedPostfixLf()
        '此处无法使用VB的Array函数
        operators_NeedPrefixLf = "},if(,if( ,for(, for (,return".Split(",")
        operators_NeedPostfixLf = "{".Split(",")

        For Each i In operators_NeedPrefixLf
            PrefixLf(Content, i)
        Next
        For Each i In operators_NeedPostfixLf
            PostfixLf(Content, i)
        Next

        Content = Content.Replace(vbCrLf, vbLf)
        Content = Content.Replace(vbCr, vbLf)
        MergeAll(Content, " " + vbLf, vbLf)
        MergeAll(Content, vbLf + vbLf, vbLf)

        '调用ALT+F8格式化代码(在我的机器上会自动在行尾增加空格,因此上面的替换仅为处理{}使用,具体的去除行尾空格,已使用查找替换实现)
        DTE.ActiveDocument.Selection.Text = Content
        DTE.ActiveDocument.Selection.SelectAll()
        DTE.ExecuteCommand("Edit.FormatSelection")

        DTE.ActiveDocument.Selection.SelectAll()

        '将Tab替换成四个空格
        '由于DTE.ActiveDocument.Selection.Text = Content会自动进行格式化,
        '所以不能用代码进行替换再赋值,否会会导致多余的空格。
        '通过查找替换功能实现
        DTEReplaceAll(vsFindTarget.vsFindTargetCurrentDocumentSelection, vbTab, "    ")
        '结束处理
    End Sub
End Module


 

 Sub写好之后,就是将之应用到VS。

点击VS的菜单:工具-》选项,切换到环境-》键盘:


在显示命令包含下的输入框中输入先前的模块名或Sub的名称,等上1-2秒钟,会将过滤后的结果刷新在输入框下发的列表中:

为VS2010编写IDE宏_第1张图片

选中对应的宏(刚刚我们所编写的Sub),然后将光标放在“按快捷键P”下方的输入框中,按一个快捷键,如果该快捷键已经被其它命令占用,会在“快捷键的当前使用对象U”下方的下拉框中显示出来:

为VS2010编写IDE宏_第2张图片

此时按Backspace,删除快捷键,重新选择一个(注意,一定要按Backspace删除,不要直接继续按),直到该快捷键未被占用(我选到的时候ALT+T),然后点击“分配”按钮,点击确定关闭选项窗口。

然后,打开一个源码文档,按下快捷键(我的是ALT+T)试试效果吧。

如果觉得不好,就修改Sub,直到自己满意为止。

 

补充:

如果发现有些IDE已经实现的功能而自己不会写,可以使用VS的宏记录功能:

按Ctrl+Shift+R或者点击菜单项“工具-〉宏-〉记录TemporaryMacro”,然后执行VS动作(比如执行查找替换),完毕后停止宏记录,然后打开宏编辑器,打开RecordingModule,代码全在这里头。

你可能感兴趣的:(为VS2010编写IDE宏)