Microsoft MVP성태의 닷넷 이야기
VS.NET IDE: 95. Macros for Visual Studio 2013 [링크 복사], [링크+제목 복사],
조회: 26075
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 2개 있습니다.)

Macros for Visual Studio 2013

Visual Studio 2012부터 매크로 탐색기가 없어진 것을 그동안 Visual Commander로 겨우 만회할 수 있었는데요.

Visual Studio 2012/2013에서의 매크로 구현 - Visual Commander
; https://www.sysnet.pe.kr/2/0/1767

드디어 마이크로소프트의 "Visual Studio Platform Team"에서 직접 만든 (비록 정식 제품에 포함되는 유형은 아니지만) 매크로 확장이 배포가 되었습니다. ^^

Macros for Visual Studio 2013
; https://visualstudiogallery.msdn.microsoft.com/d3fbf133-e51b-41a2-b86f-9560a96ff62b

설치 후, Visual Studio 2010에서와 같이 "Alt + F8" 단축키로 "Macro Explorer"를 띄우기 위해 "Tools" / "Options" / "Keyboard"에 가서 할당(Assign)하면 끝!

vs2013_macro_explorer_1.png

마이크로소프트 측에서 2012부터 매크로를 없앴던 이유는, 매크로 사용자가 별로 많지 않은 반면 내부적으로 유지해야 하는 비용이 너무 커서였다고 했습니다. 따라서, 이렇게 확장 도구 유형으로 제공함으로써 '제품' 수준의 품질은 필요하지 않으면서 매크로를 요구하는 '일부 사용자'에게 해답은 줄 수 있게 된 것입니다.




하지만, 아쉬운 점이 좀 있습니다. 우선, 언어가 ".NET 언어"가 아닌 "Javascript"만 지원한다는 점입니다. 이 때문에 기존 매크로를 보유하고 있는 경우 마이그레이션하는데 시간이 걸릴 뿐만 아니라 일부 코드는 "Javascript"의 한계로 인해 변환 자체가 불가능한 경우도 있습니다. 일례로, 그동안은 .NET Framework의 BCL 클래스를 쉽게 이용할 수 있었지만 Javascript로 바뀐 이상 BCL 클래스를 활용하는 것은 물 건너 간 것입니다.

또 한가지 불편한 점은, 아직 초기라서 그런지 '공통 라이브러리'로써의 자바스크립트 관리가 없습니다. 따라서, A 매크로에서 SetText라는 함수를 정의했다면 B 매크로 파일에서 A 매크로 파일에 포함된 SetText를 재사용할 수는 없고 동일한 소스 코드를 복제해서 보유하고 있어야 합니다.

현재로써는... 그 정도! ^^




개인적으로 프로그래밍 이외에 Visual Studio 편집기를 지금의 이 블로그에 글을 쓰는 용도로 사용하고 있습니다. 정해진 포맷팅 몇 개를 Visual Studio의 매크로를 이용해 처리하고 있는데, 하필 2012부터 매크로가 사라져서 어쩔 수 없이 컴퓨터에 2010, 2013을 함께 설치해 두고 있었습니다. 물론, 지난번에 소개한 "Visual Studio 2012/2013에서의 매크로 구현 - Visual Commander" 확장이 있었는데 차일피일 마이그레이션을 미뤄오고 있었습니다. 어차피 2010에서 되기 때문에 크게 불편하지 않았던 것인데요.

이번에는 마이크로소프트가 공식적으로 확장을 내놓았으니 마음먹고 한번 마이그레이션을 해보았습니다. 다행히, 제가 작성한 매크로의 경우 javascript로 모두 변환이 가능했는데요. 그래도 일부 매크로 기능이 쉽게 되지는 않아서 이를 공유해 봅니다.


1. 파일 저장

기존의 VB.NET 매크로에서는 단순히 .NET BCL에서 제공되는 File.WriteAllText 메서드를 사용하면 되지만, javascript에서는 그럴 수가 없습니다. 이에 대한 우회 방법을 매크로 탐색기를 설치하면 제공되는 기본 예제 중에서 "Samples/Editor/Save Backup" 코드를 보고 찾아냈습니다.

간단히 정리하면, Visual Studio로 하여금 "New File" 메뉴를 실행하고 텍스트를 넣어둔 다음 "Save"를 시키고 문서를 닫는 것입니다.

function SaveAsFile(fileText) {
    var fileName = dte.ActiveDocument.FullName + ".html";

    if (typeof (dte.ActiveDocument) != undefined) {
        var saveChangesNo = 2;

        // Create the temp document, save, then close
        dte.ItemOperations.NewFile("General\\Text File");
        dte.ActiveDocument.Object("TextDocument").Selection.Insert(fileText);
        dte.ActiveDocument.Save(fileName);
        dte.ActiveDocument.Close(saveChangesNo);
    }
}

작은 문제가 하나 있다면... 이 함수를 써 보니, Visual Studio를 실행해서 처음 실행하는 경우 다음과 같은 오류 창이 뜹니다.

An exception has been encountered. This may be caused by an extension.

You can get more information by examining the file 'c:\users\[계정]\AppData\Roaming\Microsoft\VisualStudio\12.0\ActivityLog.xml'

에러는 발생하지만, 다시 실행하면 이후부터는 아무런 문제없이 잘 동작하기 때문에 감수할 수 있습니다. 그 외에, 새로운 문서를 순간적으로 추가/삭제하기 때문에 화면이 잠시 깜빡이는 현상이 발생합니다. ^^;


2. 클립보드 복사

또 한가지 문제는 클립보드 사용입니다.

VS.NET - 매크로 함수내에서 클립보드 API 사용
; https://www.sysnet.pe.kr/2/1/628

VB.NET 매크로에서는 단순히 System.Windows.Forms 어셈블리의 Clipboard 타입을 사용하면 됐지만, javascript로 오면서 그게 안됩니다. 혹시나 싶어 "window.clipboardData.setData" 함수를 써봤지만 오류를 낼 뿐입니다.

이 역시 우회 방법을 위에서 설명한 "1. 파일 저장"과 비슷한 방식으로 해결했습니다. 즉, '빈 파일' 하나 생성하고 "Edit.SelectAll"을 실행해 전체 텍스트를 선택한 다음 "Edit.Cut"으로 클립 보드에 복사한 후 문서를 닫는 것입니다.

function SetClipboardData(iFileText)
{
    dte.UndoContext.Open("ToClipboard");

    if (typeof (dte.ActiveDocument) != undefined) {
        var saveChangesNo = 2;

        // Create the temp document, save, then close
        dte.ItemOperations.NewFile("General\\Text File");
        dte.ActiveDocument.Object("TextDocument").Selection.Insert(iFileText);

        dte.ExecuteCommand("Edit.SelectAll");
        dte.ExecuteCommand("Edit.Cut");

        dte.ActiveDocument.Close(saveChangesNo)     // Already saved with line above, don't need to save again.
    }

    dte.UndoContext.Close();  
}


3. 본문에 텍스트 삽입

이를 위해 매크로 확장에서 기본적으로 "Macro.InsertText" 함수를 제공합니다.

Macro.InsertText("TEST");

문제는, 이것의 효율이 그다지 좋지 않습니다. 긴 문장으로 테스트해보면 마치 사람이 빠르게 입력하듯 동작하기 때문에 느립니다. 그래서, 그냥 다음과 같은 함수를 만들어서 동작시키는 것이 권장됩니다.

var selection = dte.ActiveDocument.Selection;

var text = "// 주석: " + selection.Text;

SetText(selection, text);

function SetText(iSelection, iText) {
    var prop = dte.DTE.Properties("TextEditor", "PlainText").Item("IndentStyle");
    var oldIndent = prop.Value;
    prop.Value = 0;

    iSelection.Text = iText;

    prop.Value = oldIndent;
}

그런데, 여기서 만족할 수 없습니다. 이렇게 처리한 경우 텍스트 입력은 빠르게 되지만 'Ctrl + Z' 키를 눌러 Undo 작업을 하면 한줄씩 다시 undo 작업이 이뤄지면서 취소 작업에 시간이 걸립니다. 따라서, 단 한번의 'Ctrl + Z'키로 Undo를 할 수 있도록 UndoContext 처리를 해주면 됩니다.

function SetText(iSelection, iText) {
    dte.UndoContext.Open("SetTextContext");
    
    var prop = dte.DTE.Properties("TextEditor", "PlainText").Item("IndentStyle");
    var oldIndent = prop.Value;
    prop.Value = 0;

    iSelection.Text = iText;

    prop.Value = oldIndent;

    dte.UndoContext.Close();
}




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 7/10/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2016-08-19 12시57분
Visual Studio's most useful (and underused) tips
; http://www.hanselman.com/blog/VisualStudiosMostUsefulAndUnderusedTips.aspx
정성태

... 136  137  138  139  140  141  142  [143]  144  145  146  147  148  149  150  ...
NoWriterDateCnt.TitleFile(s)
1479정성태8/14/201325148오류 유형: 183. IIS - 바인딩 추가 시 Object reference not set to an instance of an object 오류 [5]
1478정성태8/14/201328474오류 유형: 182. 윈도우 정품 활성화 오류 - 0x80070426
1477정성태8/14/201327315VC++: 71. codeplex의 Project Austin - 실감나게 책장 넘기는 표현
1476정성태8/13/201335807디버깅 기술: 55. Windbg - 윈도우 핸들 테이블 (2)
1475정성태8/12/201334914.NET Framework: 377. 프로세스가 종료된 후에도 소켓이 살아있다면?파일 다운로드1
1474정성태8/10/201330955오류 유형: 181. 윈도우 8 - WmiPrvSE.exe 프로세스가 CPU 소비하는 현상
1473정성태8/8/201327778VC++: 70. Win32 socket이 Thread-safe할까? [1]파일 다운로드1
1472정성태8/7/201326205.NET Framework: 376. .NET 2.0의 유니코드 관련 문자열 비교 오류
1471정성태8/7/201331008개발 환경 구성: 193. .aspx 확장자 대신 .html 확장자를 사용하는 방법
1470정성태8/6/201326983오류 유형: 180. DISM.exe 0xc1510111 실행 오류
1469정성태8/6/201324016.NET Framework: 375. System.Net.Sockets.Socket이 Thread-safe할까? [2]파일 다운로드1
1468정성태8/6/201322161오류 유형: 179. IIS - No connection could be made because the target machine actively refused it 127.0.0.1:80
1467정성태8/5/201325589Java: 16. IE에 로드된 Java Applet의 다운로드 위치를 확인하는 방법
1466정성태7/27/201331181.NET Framework: 374. C#과 비교한 C++ STL vector 성능 [7]파일 다운로드1
1465정성태7/18/201334481기타: 33. C:\Windows\Installer 폴더의 용량 줄이기 [3]
1464정성태7/15/201322733오류 유형: 178. Visual Studio 2012 Express - ImportCardinalityMismatchException
1463정성태7/15/201323428오류 유형: 177. [DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or access denied.
1462정성태7/5/201326744VC++: 69. geek스러운 C/C++ 퀴즈 문제 [2]
1461정성태6/27/201343302.NET Framework: 373. C# 문자열의 인코딩이란?
1460정성태6/17/201325146.NET Framework: 372. PerformanceCounter - Category does not exist. [1]
1459정성태6/15/201328789Windows: 74. 한글 키가 아닌 영문 키를 기본으로 선택하는 방법 [5]
1458정성태6/13/201329635.NET Framework: 371. CAS Lock 방식이 과연 성능에 얼마나 도움이 될까요? [1]파일 다운로드1
1457정성태6/13/201325803개발 환경 구성: 192. "Probabilistic Programming and Bayesian Methods for Hackers" 예제 코드 실행 방법
1456정성태6/5/201334471.NET Framework: 370. C# - WebKit .NET 사용 [2]파일 다운로드1
1455정성태6/1/201328269.NET Framework: 369. ThreadPool.QueueUserWorkItem의 실행 지연 [4]파일 다운로드1
1454정성태5/31/201326279Java: 15. Java 7 Control Panel 실행시키는 방법
... 136  137  138  139  140  141  142  [143]  144  145  146  147  148  149  150  ...