原文 : A Visual Studio to Visual Studio Code Snippet Converter
作者 : Rick Strahl
譯者 : 張蘅水
導(dǎo)語(yǔ)
和原文作者一樣察绷,水弟我現(xiàn)在也是使用 VS Code 和 Rider 作為主力開發(fā)工具恬砂,尤其是 VS Code 可以跨平臺(tái)蚜点,又有豐富的插件支持和多種編程語(yǔ)言支持衬衬。當(dāng)我從 VS 轉(zhuǎn)移到以 VS Code 的開發(fā)過程中轧抗,遇到的最大問題就是代碼提示的不完善(被 VS 和 R# 調(diào)教壞了,總想按 tab 鍵)县忌。當(dāng)我看到原文作者通過從 VS 中導(dǎo)出代碼片段到 VS Code 時(shí)筷畦,瞬間被吸引到了。 雖然在不知不覺中用了 VS 自帶的代碼片段黍判,但我從來沒有想過要自定義專屬的代碼片段豫尽,最多也是制作用于項(xiàng)目的模板(方便創(chuàng)建特定的類型文件)。雖然導(dǎo)出到 Rider 不是很完美样悟,但 Rider 自帶了 R#拂募,對(duì)這方面的需求還是很少的庭猩。
譯文:
Visual Studio 內(nèi)置了非常好用的代碼片段工具窟她,多年來我一直在使用它來創(chuàng)建大量有用的擴(kuò)展片段,使我的日常開發(fā)更容易蔼水。我有很多 C# 代碼片段震糖,但更多的是用于 HTML 、自定義的 Bootstrap 代碼片段趴腋,乃至復(fù)雜的 HTML 控件代碼段吊说。偶爾也會(huì)用到 JavaScript 、XAML 甚至Powershell 优炬。
在過去的幾年里颁井,我越來越多地使用其他工具與 Visual Studio 結(jié)合使用。特別是 Visual Studio Code 和 JetBrains Rider蠢护。
在多年的使用 Visual Studio 中雅宾,我已經(jīng)累積了 130 多個(gè)代碼片段。每當(dāng)我在其他開發(fā)環(huán)境中工作時(shí) ( VS Code 或者 Rider)葵硕,我真的很需要他們眉抬,特別是要寫一大段 HTML的時(shí)候贯吓,總是要去痛苦地去對(duì)應(yīng)的文檔站點(diǎn)查找。使用代碼片段功能蜀变,只需幾次擊鍵就會(huì)自動(dòng)填充我自定義的特定代碼悄谐,每天可節(jié)省大量時(shí)間。
所以我很需要代碼片段功能库北,有時(shí)我打開 Visual Studio 只是為了找到需要的 HTML 的代碼片段爬舰,然后將它們粘貼回 VS Code 或 Rider。雖然繁瑣寒瓦,但是仍然從文檔網(wǎng)站中復(fù)制代碼洼专,然后手動(dòng)修改代碼來得便捷。如果能在每個(gè)對(duì)應(yīng)的開發(fā)環(huán)境中直接執(zhí)行代碼片段的功能孵构,那就太好了屁商!
因此,在過去的幾個(gè)周末颈墅,我做了一個(gè)將 Visual Studio 中的代碼片段導(dǎo)出到 VS Code 中的小工具蜡镶,同時(shí)盡量能導(dǎo)出到 JetBrains Rider 。
如果你感興趣恤筛,可以在GitHub上找到代碼:
另外說一句官还,這還只是一個(gè)菜鳥項(xiàng)目,并不能保證它支持所有類型的的代碼片段毒坛。只是我自己擁有的 137 個(gè)代碼片段都完美地移植到 VS Code望伦,并且能夠運(yùn)行。同時(shí)我還可以重新導(dǎo)出煎殷, 輕松地導(dǎo)出新創(chuàng)建的代碼片段屯伞,這樣就可以對(duì)比和更新了。
對(duì)于 Rider 而言豪直,操作起來更為復(fù)雜劣摇,因?yàn)?Rider 有一種瘋狂的機(jī)制,可以將模板存儲(chǔ)在內(nèi)部的單個(gè)配置文件中弓乙。它還為 .NET相關(guān)的片段 (C#末融、VB、F#暇韧、Razor勾习、ASP.NET )和 基于 Web ( html、css懈玻、js 等)的代碼片段使用了多個(gè)完全不同的存儲(chǔ)引擎巧婶。所以工具目前僅支持一次性導(dǎo)出 .NET 相關(guān)代碼段,因?yàn)?Rider 中基于 GUID 的密鑰系統(tǒng)不允許在沒有 GUID 的情況下查找現(xiàn)有代碼段。后面我們?cè)僭敿?xì)介紹粹舵。
代碼片段轉(zhuǎn)換器
你可以通過借助 .NET 全局工具 (.NET Global SDK Tool )钮孵,使用 Nuget 下載和運(yùn)行代碼片段轉(zhuǎn)換器:
dotnet tool install --global dotnet-snippetconverter
如果您不想安裝并只運(yùn)行該工具,您可以克隆或下載Github倉(cāng)庫(kù)眼滤,然后:
cd .\SnippetConverter\
dotnet run
安裝后巴席, 可以通過指向文件夾或單個(gè)文件將 Visual Studio 中的代碼片段批量或單獨(dú)轉(zhuǎn)換為 VS Code 支持的代碼片段。
snippetconverter ~2017 -r -d
或者诅需,您可以像下面這張屏幕截圖那樣指定輸出文件:
有幾個(gè)選項(xiàng)可用于轉(zhuǎn)換單個(gè)片段和文件夾漾唉,使用前綴,遞歸文件夾堰塌,輸出生成文件的路徑等:
Syntax:
-------
SnippetConverter <sourceFileOrDirectory> -o <outputFile>
--mode --prefix --recurse --display
Commands:
---------
HELP || /? This help display
Options:
--------
sourceFileOrDirectory Either an individual snippet file, or a source folder
Optional special start syntax using `~` to point at User Code Snippets folder:
~ - Visual Studio User Code Snippets folder (latest version installed)
~2017 - Visual Studio User Code Snippets folder (specific VS version 2019-2012)
-o <outputFile> Output file where VS Code snippets are generated into (ignored by Rider)
Optional special start syntax using `~` to point at User Code Snippets folder:
%APPDATA%\Code\User\snippets\ww-my-codesnippets.code-snippets
~\ww-my-codesnippets.code-snippets
if omitted generates `~\exported-visualstudio.code-snippets`
-m,--mode vs-vscode (default)
vs-rider experimental - (C#,VB.NET,html only)
-d display the target file in Explorer
-r if specifying a source folder recurses into child folders
-p,--prefix snippet prefix generate for all snippets exported
Example: `ww-` on a snippet called `ifempty` produces `ww-ifempty`
Examples:
---------
# vs-vscode: Individual Visual Studio Snippet
SnippetConverter "~2017\Visual C#\My Code Snippets\proIPC.snippet"
-o "~\ww-csharp.code-snippets" -d
# vs-vscode: All snippets in a folder user VS Snippets and in recursive child folers
SnippetConverter "~2017\Visual C#\My Code Snippets" -o "~\ww-csharp.code-snippets" -r -d
# vs-vscode: All the user VS Snippets and in recursive child folders
SnippetConverter ~2017\ -o "~\ww-all.code-snippets" -r -d
# vs-vscode: All defaults: Latest version of VS, all snippets export to ~\visualstudio-export.code-snippets
SnippetConverter ~ -r -d --prefix ww-
# vs-rider: Individual VS Snippet
SnippetConverter "~2017\proIPC.snippet" -m vs-rider -d
# vs-rider: All VS Snippets in a folder
SnippetConverter "~2017\Visual C#\My Code Snippets" -m vs-rider -d
上面的用例應(yīng)該足夠說明用途了赵刑。如果還想要了解更多信息,請(qǐng)接著往下看......
什么是 VS Code 的代碼片段
如果您不熟悉或不使用代碼片段场刑,那您并不是少數(shù)人般此。它們?cè)?Visual Studio 中幾乎是一個(gè)隱藏的功能,這是一個(gè)恥辱牵现,因?yàn)樗鼈兪欠浅S杏玫纳a(chǎn)力工具铐懊。不幸的是,Visual Studio 沒有任何有用的內(nèi)置UI來創(chuàng)建這些片段瞎疼,因此大多數(shù)開發(fā)人員都沒有充分利用此功能科乎。Visual Studio 只能蹩腳地點(diǎn)擊 ** 工具 - > 代碼片段管理器 ** 菜單 ,除了一個(gè)查看器之外贼急,它沒有其他管理功能茅茂,僅僅是查看哪些片段是可用的,沒有內(nèi)置的方法來創(chuàng)建或編輯片段太抓,甚至跳轉(zhuǎn)到并查看代碼片段空闲。
但是,代碼片段僅僅只是位于用戶目錄的 Documents 文件夾下的 XML 文件腻异。它們非常容易創(chuàng)建和更新进副,僅僅是原始的 XML 文件,用 VS Code 等文本編輯器去做代碼片段和高亮實(shí)在是非常簡(jiǎn)單悔常。盡管在 Visual Studio 中有一些提供 UI 操作的劣質(zhì)插件,但它們往往比原始的代碼片段文件更麻煩给赞。
創(chuàng)建新代碼段的最佳方法是復(fù)制現(xiàn)有代碼段并對(duì)其進(jìn)行修改以滿足您的需求机打。
一般來說,代碼片段位于 (水弟我是直接用 Everything搜索的):
<Documents>\Visual Studio 2017\Code Snippets
每種語(yǔ)言技術(shù)都有自己的子文件夾進(jìn)行分組片迅,但僅僅是文件夾上的區(qū)分而已残邀。代碼片段實(shí)際上通過 XML中的 Language
屬性確定它們適用的語(yǔ)言。
Visual Studio在此位置附帶了許多代碼段,您可以使用這些代碼段作為新代碼段的模板進(jìn)行學(xué)習(xí)芥挣。
<?xml version="1.0" encoding="utf-8"?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<CodeSnippet Format="1.0.0">
<Header>
<Title>Property with INotifyPropertyChange raised</Title>
<Description>Control Property with Attributes</Description>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
<Shortcut>proIPC</Shortcut>
</Header>
<Snippet>
<References />
<Imports />
<Declarations>
<Literal Editable="true">
<ID>name</ID>
<Type></Type>
<ToolTip>Property Name</ToolTip>
<Default>MyProperty</Default>
<Function></Function>
</Literal>
<Literal Editable="true">
<ID>type</ID>
<Type></Type>
<ToolTip>Property Type</ToolTip>
<Default>string</Default>
<Function></Function>
</Literal>
</Declarations>
<Code Language="csharp" Kind="method decl" Delimiter="$"><![CDATA[public $type$ $name$
{
get { return _$name$; }
set
{
if (value == _$name$) return;
_$name$ = value;
OnPropertyChanged(nameof($name$));
}
}
private $type$ _$name$;
]]></Code>
</Snippet>
</CodeSnippet>
</CodeSnippets>
一旦文件存在或更新了驱闷,Visual Studio 無需重啟,就能立即發(fā)現(xiàn)并使用空免。在相關(guān)的 (如 C#) 編輯器中空另,立馬就能看到智能提示中的代碼段:
它插入對(duì)應(yīng)的模板并允許您編輯在模板中聲明的 $expr$
占位符:
這個(gè) C# 代碼片段示例, 是 VS 中最常見的語(yǔ)言蹋砚。如您所見扼菠, XML文件中的 <Code>
節(jié)點(diǎn)定義模板文本,Shortcut
節(jié)點(diǎn)定義觸發(fā)提示的按鍵坝咐,你可以使用在 <Declaration>
節(jié)點(diǎn)中使用類似 $txt$
占位符來定義參數(shù)循榆,同樣的占位符在多個(gè)地方出現(xiàn)也能同步更改。
對(duì)于我來說墨坚,最有用和最常用的代碼片段時(shí)用于插入 HTML 代碼秧饮,特別是在定義 Bootstrap 結(jié)構(gòu)或其他很難記住語(yǔ)法的自定義控件。我喜歡在瀏覽文檔網(wǎng)站后創(chuàng)建一個(gè)對(duì)應(yīng)的片段泽篮,這樣就很方便使用浦楣。用多幾次,省下來的時(shí)間就賺翻了咪辱≌窭停花費(fèi)幾分鐘設(shè)置模板可以節(jié)省大量時(shí)間去輸入重復(fù)代碼,尤其是您每次都要浪費(fèi)時(shí)間查找相同的 Bootstrap 代碼時(shí)油狂。??
前綴以及代碼片段包
Visual Studio Marketplace中還有許多可用的代碼片段历恐,您可以安裝使用一整套預(yù)設(shè)的代碼片段。例如专筷,Bootstrap Snippet 包就內(nèi)置了一堆以 bs-
為前綴的代碼片段弱贼。
即使您自己有專屬的代碼片段,最好為您的代碼片段創(chuàng)建一個(gè)前綴磷蛹,以便您可以在智能提示的海洋中輕松地找到它們吮旅。我一般使用 ww-
作為大多數(shù)代碼片段的前綴。不幸的是味咳,我自己沒有很好得遵循這個(gè)建議庇勃,還是有不少代碼片段沒有這么做。
構(gòu)建轉(zhuǎn)換器
因?yàn)槲以?Visual Studio 大量使用了代碼片段槽驶,所以我做了一個(gè)將 Visual Studio 中的代碼片段遷移到 VS Code 中的小工具责嚷,同時(shí)盡量能遷移到 JetBrains Rider 。
我想可能還有其他人需要用到掂铐,所以我把它作為 .NET Global Tool 控制臺(tái)應(yīng)用程序發(fā)布罕拂,以便快速安裝:
dotnet tool install dotnet-snippetconverter
您需要 .NET Core 2.1 SDK或更高版本 才能運(yùn)行它揍异。
以下示例命令將代碼片段從 Visual Studio 遷移到 VS Code,稍后再討論遷移到 Rider 的事
安裝后爆班,您可以使用以下命令快速將所有 Visual Studio 代碼片段轉(zhuǎn)換為 VS Code 可以接受的格式衷掷。
snippetconverter ~ -r -d
這將轉(zhuǎn)換最新安裝的 Visual Studio 版本(2017,2019等)中的所有代碼片段,并在位于%appdata%\Code\User\snippets
路徑的 VS Code 的代碼文件夾中創(chuàng)建單獨(dú)的 visualstudio-exported.code-snippets
文件夾柿菩。
您還可以導(dǎo)出特定 VS 版本的代碼片段:
snippetconverter ~2017 -r -d
或特定文件夾:
snippetconverter "~2017\Visual C#\My Code Snippets" -r -d -o "~\ww-csharp.code-snippets"
其中輸入和輸出文件夾選項(xiàng)中的路徑都是可選的戚嗅,示例中的~
是物理片段路徑的占位符,會(huì)指向 Visual Studio(%Documents%\Visual Studio <year>\Code Snippets
)和 VS Code(%appdata%\Code\User\Snippets\
)中存放代碼片段的基本位置碗旅,因此您不必每次都指定完整路徑渡处。您高興的話,也可以使用合格的全路徑祟辟。
最后医瘫,您還可以導(dǎo)出單個(gè)文件:
snippetconverter "~2017\Visual C#\My Code Snippets\proIPC.snippet" -d -o "~\ww-csharp.code-snippets"
如果 VS Code 中已存在該代碼片段,則會(huì)覆蓋更新旧困,所以每次重新運(yùn)行都會(huì)更新對(duì)應(yīng)的代碼片段醇份。
運(yùn)行遷移工具后,在VS Code 中通過前綴或者快捷方式就可以立即使用:
在 Visual Studio 中多個(gè)占位符輸入也是支持的:
同步代碼片段
目前只支持從Visual Studio 單向 遷移到到 VS Code吼具。這意味著如果要保持 Visual Studio 和 VS Code 之間的代碼段同步僚纷,最好是在 Visual Studio 中創(chuàng)建代碼片段,然后通過此工具將它們遷移到 VS Code拗盒。
VS Code 中的代碼片段
我之前討論過 Visual Studio Snippets 的代碼片段格式怖竭,現(xiàn)在讓我們看看 VS Code 中又是什么樣的。
- 存放在
%AppData\Code\User\snippets
- 使用 JSON 格式化
- 命名為
lang.json
- 或者是
<name>.code-snippet
的命名格式 - 可以包含一個(gè)或者多個(gè)代碼片段
轉(zhuǎn)換器之所以導(dǎo)出為 .code-snippet
文件格式陡蝇,是因?yàn)槭褂?lang.json
很容易造成命名沖突痊臭。如果默認(rèn)的 visualstudio-export.code-snippets
不能使用,則使用 -o
來指定輸出文件登夫。
VS Code 代碼片段文件是 JSON广匙,它們看起來像:
{
"proipc": {
"prefix": "proipc",
"scope": "csharp",
"body": [
"public ${2:string} ${1:MyProperty}",
"{",
" get { return _${1:MyProperty}; }",
" set",
" {",
" if (value == _${1:MyProperty}) return;",
" _${1:MyProperty} = value;",
" OnPropertyChanged(nameof(${1:MyProperty}));",
" }",
"} ",
"private ${2:string} _${1:MyProperty};",
""
],
"description": "Control Property with Attributes"
},
"commandbase-object-declaration": {
"prefix": "commandbase",
"scope": "csharp",
"body": [
" public CommandBase ${1:CommandName}Command { get; set; }",
"",
" void Command_${1:CommandName}()",
" {",
" ${1:CommandName}Command = new CommandBase((parameter, command) =>",
" {",
" $0",
" }, (p, c) => true);",
" }",
""
],
"description": "Create a CommandBase implementation and declaration"
}
}
VS Code 的代碼模板在概念上更簡(jiǎn)單,只有模板恼策,前綴和范圍鸦致,以及使用字符串插值和約定來確定如何定義占位符。當(dāng)然還有其他字段可以填充涣楷,但大多數(shù)值是可選的分唾,對(duì)于從 Visual Studio 轉(zhuǎn)換過來的代碼片段用不到。
您可以在此處找到Visual Studio代碼段模板文檔:
但是實(shí)際上总棵,自己手動(dòng)創(chuàng)建模板鳍寂,定義 JSON中的 body
屬性還是有難度的,因?yàn)樽址赡苤皇且粋€(gè)字符串?dāng)?shù)組(yuk)情龄,也可能是一個(gè)可以輸入的類型迄汛。好在只是從 Visual Studio 代碼片段轉(zhuǎn)換,還是很容易生成對(duì)應(yīng)的模板...
咦骤视?導(dǎo)出到 Rider
轉(zhuǎn)換器某種程度上可以適配到 Rider鞍爱,但功能有限。因?yàn)镽ider 使用令人抓狂的模式來存儲(chǔ)代碼片段专酗,使用 GUID 來標(biāo)識(shí)的 XML 文件。
%USERPROFILE%\.Rider2018.2\config\resharper-host\GlobalSettingsStorage.DotSettings
讓我們看看幾個(gè)導(dǎo)出的模板效果:
<root>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Reformat/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Shortcut/@EntryValue">proipc</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/ShortenQualifiedReferences/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Text/@EntryValue">public $type$ $name$
{
get { return _$name$; }
set
{
if (value == _$name$) return;
_$name$ = value;
OnPropertyChanged(nameof($name$));
}
}
private $type$ _$name$;
</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Field/=name/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Field/=name/Expression/@EntryValue">complete()</s:String>
<s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Field/=name/Order/@EntryValue">0</s:Int64>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Field/=type/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Field/=type/Expression/@EntryValue">complete()</s:String>
<s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=720E28E0ECFD4CA0B80F10DC82149BD4/Field/=type/Order/@EntryValue">1</s:Int64>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/@KeyIndexDefined">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Applicability/=Live/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Reformat/@EntryValue">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Shortcut/@EntryValue">seterror</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/ShortenQualifiedReferences/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Scope/=C3001E7C0DA78E4487072B7E050D86C5/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Scope/=C3001E7C0DA78E4487072B7E050D86C5/Type/@EntryValue">InCSharpFile</s:String>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Text/@EntryValue">
public string ErrorMessage {get; set; }
protected void SetError()
{
this.SetError("CLEAR");
}
protected void SetError(string message)
{
if (message == null || message=="CLEAR")
{
this.ErrorMessage = string.Empty;
return;
}
this.ErrorMessage += message;
}
protected void SetError(Exception ex, bool checkInner = false)
{
if (ex == null)
this.ErrorMessage = string.Empty;
Exception e = ex;
if (checkInner)
e = e.GetBaseException();
ErrorMessage = e.Message;
}
</s:String>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Field/=busObject/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Field/=busObject/Expression/@EntryValue">complete()</s:String>
<s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Field/=busObject/Order/@EntryValue">0</s:Int64>
<s:Boolean x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Field/=NewLiteral/@KeyIndexDefined">True</s:Boolean>
<s:String x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Field/=NewLiteral/Expression/@EntryValue">complete()</s:String>
<s:Int64 x:Key="/Default/PatternsAndTemplates/LiveTemplates/Template/=E88A906D39C741C0A3B8095C5063DADE/Field/=NewLiteral/Order/@EntryValue">1</s:Int64>
</root>
使用這種瘋狂的格式,無法分辨一組代碼片段的開始和結(jié)束的位置佑笋。每個(gè)代碼片段都有多個(gè) Key翼闹,加上 GUID 標(biāo)識(shí)蒋纬,這使得匹配現(xiàn)有的代碼段來判斷是否存在的目的幾乎不可能實(shí)現(xiàn)。
據(jù)我所知蜀备,沒有找到任何相關(guān)鍵值配置的文檔关摇,也沒有如何存儲(chǔ)的文檔。很有可能存在其他存儲(chǔ)選項(xiàng)碾阁,但看起來 Rider 并沒有為代碼片段設(shè)置編輯功能。如果您有更好的開發(fā)人員文檔宪睹,請(qǐng)發(fā)表評(píng)論艰猬。
出于這個(gè)原因,Rider 導(dǎo)入是一次性的冠桃,如果您導(dǎo)出兩次相同的片段,它們就會(huì)翻倍胸蛛。
為了測(cè)試樱报,我在 Rider 的導(dǎo)出文件中添加了一個(gè)標(biāo)記鍵。然后民珍,在我導(dǎo)入相同的代碼片段時(shí),我會(huì)刪除了之前添加的代碼片段嚷量。很簡(jiǎn)陋蝶溶,也只是測(cè)試階段。如果相關(guān)的配置發(fā)生了變化抖所,則可能會(huì)失效田轧。
此格式僅適用于 Rider 支持的 .NET 特定代碼類型:.NET Languages暴匠,Razor 和包含 HTML 模板的 WebForms涯鲁。其他格式( JavaScript抹腿、HTML 、CSS)則使用完全獨(dú)立的格式警绩,我沒有精力在實(shí)現(xiàn)相關(guān)的功能。對(duì)于 Rider后室,我主要關(guān)心的是 C# 和 HTML 模板混狠,能正常運(yùn)行就好了。
只需導(dǎo)出特定文件夾贡避,如 C# 文件夾或 HTML 代碼段予弧,而不是批量導(dǎo)出整個(gè)代碼片段文件夾刮吧。
SnippetConverter "~2017\Visual C#\My Code Snippets" -m vs-rider -d
SnippetConverter "~2017\Code Snippets\Visual Web Developer\My HTML Snippets" -m vs-rider -d
摘要
正如我前面提到的掖蛤,所有這些都是非常簡(jiǎn)陋,但對(duì)于將我全部的代碼片段從 Visual Studio 導(dǎo)出到 Visual Studio Code 是完全夠用的致讥。對(duì)于 Rider, C# 和 HTML 代碼片段導(dǎo)出也可以做到蝇恶,但是其他類型(如 JavaScript惶桐、CSS)會(huì)出現(xiàn)異常潘懊。我只是當(dāng)作個(gè)人工具,如果哪天有足夠的興趣的話救恨,我會(huì)接著完善释树,但是很大程度是需要另外搞一個(gè)完全獨(dú)立的轉(zhuǎn)換器奢啥。
我沒有測(cè)試所有的 Visual Studio 支持的文件類型,即使是VS 內(nèi)置的代碼片段也可能存在某些問題寂纪。保險(xiǎn)一點(diǎn)赌结,請(qǐng)不要批量導(dǎo)出所有代碼段,而是單獨(dú)導(dǎo)出每種類型的代碼片段拟杉。
我還是強(qiáng)烈建議使用前綴量承,因?yàn)榭梢愿菀椎卣业侥愕拇a片段,并保持它們不受影響焕梅。
現(xiàn)在這個(gè)工具對(duì)于我來說已經(jīng)足夠了卦洽,但是我很想知道我是否是少數(shù)幾個(gè)投身到代碼片段轉(zhuǎn)換的人之一??
相關(guān)資源
本文采用 知識(shí)共享署名-非商業(yè)性使用-相同方式共享 3.0 中國(guó)大陸許可協(xié)議
轉(zhuǎn)載請(qǐng)注明來源:張蘅水