Habrahabrの出版物でVisual Studioのコードの元の色を維持する方法。 色を比較します。 世論調査

こんにちは、habrayuzer! この投稿では、元の配色を保存する簡単な方法のおかげで、Habréコードをより「生きた」ものにする方法を説明します。 また、コードの色付けのさまざまなオプションを比較することをお勧めします。



まえがき



現在、HabrのWebサービスに関する最初の記事を執筆中です。 私の意見では標準の<source>タグでは定性的な構文強調効果が得られないため、最初からサードパーティのハーバーハイライターでソースコードを強調することにしました。 しかし、私が見つけた代替ハイライトは1つだけです-http://highlight.hohli.com 。 残念ながら、その着色の結果は私を刺激しませんでした。 投稿の最後に、直接比較するために6つのカラーオプションの中からそれを示します。 以前、別の蛍光ペンありました - ソースコード蛍光ペンは、 ここここでHabréについて説明されていますが、長い間機能していません 。 その後、WordにコピーするときにVisual Studioのコードが完全にその外観を保持することを思い出しました。この単純な手法が私の方法の基礎になりました。



方法



アイデアは簡単です。コードはWordにコピーされ、ドキュメントはhtml Webページとして保存され、関数はhtmlコードをHabra互換のものに変換します。 例を考えてみましょう。 この単純なコードを保存すると、次の<body>コンテンツが生成されます。ここで、すべての<span>タグを青で、スタイルの色をピンクで、表示されたテキストを茶色でマークしました。

プライベート   void Hello(){

     MessageBox .Show( "Hello Habrahabr!" );

}

Hello.htm
<body lang = RU style = 'tab-interval:35.4pt'>

<divクラス= WordSection1>



<p class = MsoNormalスタイル= 'margin-bottom:0cm; margin-bottom:.0001pt; line-height:

normal; mso-layout-grid-align:なし; text-autospace:なし '> <span lang = EN-US

style = 'font-size:9.5pt; font-family:Consolas; 色:黒 、背景:白、

mso-highlight:白; mso-ansi-language:EN-US ' > <span

style = 'mso-spacerun:yes' > </ span> </ span> <span class = GramE > <span

lang = EN-US style = 'font-size:9.5pt; font-family:Consolas; 色:青 、背景:

白; mso-highlight:白; mso-ansi-language:EN-US ' > プライベート </ span> </ span> <span

lang = EN-US style = 'font-size:9.5pt; font-family:Consolas; 色:黒 、背景:

白; mso-highlight:白; mso-ansi-language:EN-US ' > </ span> <span lang = EN-US

style = 'font-size:9.5pt; font-family:Consolas; 色:青 、背景:白、

mso-highlight:白; mso-ansi-language:EN-US ' > void </ span> <span lang = EN-US

style = 'font-size:9.5pt; font-family:Consolas; 色:黒 、背景:白、

mso-highlight:白; mso-ansi-language:EN-US ' > Hello(){ <o:p> </ o:p> </ span> </ p>



<p class = MsoNormalスタイル= 'margin-bottom:0cm; margin-bottom:.0001pt; line-height:

normal; mso-layout-grid-align:なし; text-autospace:なし '> < span lang = EN-US

style = 'font-size:9.5pt; font-family:Consolas; 色:黒 、背景:白、

mso-highlight:白; mso-ansi-language:EN-US '> <span

style = 'mso-spacerun:yes'> </ span> </ span> <span class = GramE> < span

lang = EN-US style = 'font-size:9.5pt; font-family:Consolas; 色:#2B91AF ;

背景:白; mso-highlight:白; mso-ansi-language:EN-US '> メッセージボックス </ スパン > < スパン

lang = EN-US style = 'font-size:9.5pt; font-family:Consolas; 色:黒 、背景:

白; mso-highlight:白; mso-ansi-language:EN-US '> .Show( </ span> </ span> <span

lang = EN-US style = 'font-size:9.5pt; font-family:Consolas; 色:#A31515 ;

背景:白; mso-highlight:白; mso-ansi-language:EN-US ' > &quot;こんにちは

Habrahabr !& Quot ; </ span> <span lang = EN-US style = 'font-size:9.5pt; font-family:

コンソラス; 色:黒 ;背景:白; mso-highlight:白; mso-ansi-language:

EN-US '> ); <o:p> </ o:p> </ span> </ p>



<p class = MsoNormal> <span lang = EN-US style = 'font-size:9.5pt; line-height:115%;

フォントファミリー:コンソラ; 色:黒 ;背景:白; mso-highlight:白;

mso-ansi-language:EN-US '> <span style =' mso-spacerun:yes ' > </ span> </ span> <span

style = 'font-size:9.5pt; line-height:115%; font-family:Consolas; 色:黒 ;

背景:白; mso-highlight:白 ' > } </ span> </ p>



</ div>

</ body>


ご覧のとおり、ソースコードの各行は<p>タグに変換され、その内部でテキストはネストされた<span>タグを使用してフォーマットされ、その色はstyle属性に格納されます。 変換アルゴリズムが明確になります。 「/ html / body / div / p」の<p>タグ に対して、そのコンテンツを再帰的に新しいhtmlドキュメントに変換し、同時に<font>タグを使用してテキストの色を設定します。 ネタバレの下には、結果のメソッドの完全なソースコードがあり、これは元のカラースキームに従って表示されます。 htmlを使用するために、 Html Agility Packライブラリが使用されました。



HabraCodeFormatter.cs
  1. システムを使用して ;
  2. System.IO を使用します。
  3. HtmlAgilityPack を使用
  4. 名前空間 HabraCode {
  5. パブリック スタティック クラス HabraCodeFormatter {
  6. const char spaceClassic =( char32 ;
  7. const char spaceNbsp =( char160 ;
  8. public static void Formatstring fileHtm、 bool withLineNumbers = false ){
  9. var info = new FileInfo (fileHtm);
  10. 文字列 destFile = info。 DirectoryName + "\\" +情報。 お名前 Replaceinfo。Extensionnull )+ "_result.txt" ;
  11. 形式 (fileHtm、destFile、withLineNumbers);
  12. }
  13. public static void Formatstring fileHtm、 string fileDest、 bool withLineNumbers = false ){
  14. var doc = new HtmlDocument ();
  15. doc。 ロード (fileHtm);
  16. var nodes = doc。 DocumentNode SelectNodes"/ html / body / div / p" );
  17. int spaceToDelete = getSpacesToDelete (ノード[ 0 ]);
  18. var result = new HtmlDocument ();
  19. var rootNode = result。 CreateElement" blockquote " );
  20. 結果。 DocumentNode AppendChild (rootNode);
  21. if (withLineNumbers){
  22. var nodeOl =結果。 CreateElement"ol" );
  23. rootNode AppendChild (nodeOl);
  24. rootNode = nodeOl;
  25. }
  26. foreach (ノード内の varノード){
  27. if (withLineNumbers){
  28. var nodeLi = doc。 CreateElement"li" );
  29. nodeLi。 AppendChildren (ノード。ChildNodes );
  30. ノード。 RemoveAllChildren ();
  31. ノード。 AppendChild (nodeLi);
  32. }
  33. int refSpaces = SpacesToDelete;
  34. translateNode (node、rootNode、 ref refSpaces);
  35. rootNode AppendChildresult。CreateTextNodeEnvironment。NewLine ));
  36. }
  37. 結果。 保存 (fileDest);
  38. }
  39. private static int getSpacesToDeleteHtmlNodeノード){
  40. forint index = 0 ; index < node。InnerText。Length ; index ++){
  41. if (! isSpacenode。InnerText [index])){
  42. インデックスを返します。
  43. }
  44. }
  45. 0を 返し ます
  46. }
  47. private static void translateNodeHtmlNodeノード、 HtmlNode destParent、 ref int spaceToDelete){
  48. HtmlNode destNode = destParent;
  49. スイッチ (ノード。 名前 ){
  50. ケース "o:p"
  51. ケース "p"
  52. 休憩 ;
  53. ケース 「スパン」
  54. 文字列の色= getColor (ノード);
  55. if (color!= null ){
  56. destNode = destParent。 OwnerDocumentCreateElement"font" );
  57. destNode。 SetAttributeValue"color" 、色);
  58. }
  59. 休憩 ;
  60. ケース "#text"
  61. string text = translateText (node。InnerText、 ref spacesToDelete);
  62. destNode = destParent。 OwnerDocumentCreateTextNode (テキスト);
  63. 休憩 ;
  64. ケース 「b」
  65. ケース 「li」
  66. destNode = destParent。 OwnerDocumentCreateElement (ノード。 名前 );
  67. 休憩 ;
  68. デフォルト
  69. 新しい InvalidOperationException"予期しないnode.Name" + node。Name)を スローします。
  70. }
  71. if (! ReferenceEquals (destNode、destParent)){
  72. destParent。 ChildNodes追加 (destNode);
  73. }
  74. ifnode。HasChildNodes ){
  75. foreach (ノードのHtmlNodeの。ChildNodes ){
  76. translateNode (child、destNode、 ref spaceToDelete);
  77. }
  78. }
  79. }
  80. private static string translateText文字列テキスト、 ref intスペース){
  81. ifstring。IsNullOrEmpty (text)){
  82. 戻りテキスト。
  83. }
  84. テキスト=テキスト。 Replace"http://""http&#58; //" );
  85. テキスト=テキスト。 Replace"\ r \ n""" );
  86. if (スペース> 0 &&テキスト。 長さ > =スペース&& isSpace (テキスト。 サブストリング0 、スペース))){
  87. テキスト=テキスト。 削除0 、スペース);
  88. スペース= 0 ;
  89. }
  90. テキスト=テキスト。 ReplacespaceClassic。ToString ()、 "&nbsp;" );
  91. テキスト=テキスト。 ReplacespaceNbsp。ToString ()、 "&nbsp;" );
  92. 戻りテキスト。
  93. }
  94. プライベート スタティック ブール isSpacechar ch){
  95. return (ch == spaceClassic || ch == spaceNbsp );
  96. }
  97. private static bool isSpacestring text){
  98. foreach (テキスト内の文字){
  99. if (! isSpace (ch)){
  100. falseを 返し ます
  101. }
  102. }
  103. trueを 返し ます
  104. }
  105. private static string getColorHtmlNodeノード){
  106. var attr = node。 属性 [ "スタイル" ];
  107. if (attr == null || attr。Value == null ){
  108. nullを 返し ます
  109. }
  110. 文字列 []値= attr。 価値 Splitnew [] { ';' });
  111. foreach (値の文字列値){
  112. const string prefixColor = "color:" ;
  113. トリミングされた文字列 =値。 トリム ();
  114. if (トリミングされたStartsWithprefixColor )){
  115. トリミングを返します。 削除0prefixColor。Length );
  116. }
  117. }
  118. nullを 返し ます
  119. }
  120. }
  121. }


おそらく、多くの人が私のカラーコードをカラフルすぎると呼んでいるため、不快感を覚えますが、ソースコードを操作するプロセスが大幅に改善されます。 これは、パフォーマンスを少し改善する非常に簡単な方法です。 コードに関する小さなコメント。 このクラスには、Formatメソッドの2つのオーバーロードが含まれます。必須パラメーターはソースhtmlファイルへのパスであり、オプションで行番号を追加するためのフラグです。 2番目のオーバーロードでは、最終ファイルを明示的に指定できます。指定しない場合、結果は[source_name] _result.txtとして保存されます。 getSpacesToDeleteメソッドを使用すると、最初の行の先頭のスペースの数を検索して、後続のすべての行でそれらを削除できます。



Visual Studioのソースコードのフォントと色は、メニューの[ ツール ] > [オプション ] > [環境]> [フォントと色 ]で設定します。 ただし、最初は通常、メソッドまたはプロパティの色を設定する機能はありません。 しかし、ReSharperを使用すると、そのような機会が現れます。 これを行うには、メニューReSharper>オプション>コード検査>設定で、アイテムの色の識別を有効にします。 そして、ここでは、メソッドがターコイズ色になり、クラスが従来のスキームでそのような色になり、クラスが濃い青色になるので、わずかな認知的不協和を体験できます-これをすべて下で見ることができます、色を比較します。



私のスキームでは、クラス、キーワード、およびその他の要素には古典的な色が付いていますが、メソッドおよびプロパティのためにそれらの色が追加されています。 それを試してみたい人のために、私は設定をもたらします。 xmlをスポイラーの下に.vssettings拡張子を持つファイルとして、BOMなしのUTF-8エンコーディングで保存します(HabraCode.vssettingsなど)。メニューから[ ツール ] > [インポートとエクスポート設定]> [インポート...]を選択します。 。 デフォルトでは、ウィザードは現在の設定もすべて保存します-変更のロールバックを許可します。 インポート後、フォントはデフォルトにリセットされます。カスタムフォントがある場合は、再度指定する必要があります。 また、「プレーンテキスト」設定で、背景の白色度をわずかに下げ、絶対値から#FAFAFAに下げました。



HabraCode.vssettings
<UserSettings> <ApplicationIdentity version="10.0"/> <ToolsOptions> <ToolsOptionsCategory name="Environment" RegisteredName="Environment"/> </ToolsOptions> <Category name="Environment_Group" RegisteredName="Environment_Group"> <Category name="Environment_FontsAndColors" Category="{1EDA5DD4-927A-43a7-810E-7FD247D0DA1D}" Package="{DA9FB551-C724-11d0-AE1F-00A0C90FFFC3}" RegisteredName="Environment_FontsAndColors" PackageName="Visual Studio Environment Package"> <PropertyValue name="Version">2</PropertyValue> <FontsAndColors Version="2.0"> <Categories> <Category GUID="{A27B4E24-A735-4D1D-B8E7-9716E1E3D8E0}"> <Items> <!-- --> <Item Name="Plain Text" Foreground="0x02000000" Background="0x00FAFAFA" BoldFont="No"/> <Item Name="Literal" Foreground="0x02000000" Background="0x02000000" BoldFont="Yes"/> <Item Name="Number" Foreground="0x02000000" Background="0x02000000" BoldFont="Yes"/> <Item Name="ReSharper Namespace Identifier" Foreground="0x02000000" Background="0x02000000" BoldFont="No"/> <Item Name="ReSharper Mutable Local Variable Identifier" Foreground="0x02000000" Background="0x02000000" BoldFont="No"/> <!--:  --> <Item Name="String" Foreground="0x001515A3" Background="0x02000000" BoldFont="No"/> <Item Name="String(C# @ Verbatim)" Foreground="0x001515A3" Background="0x02000000" BoldFont="No"/> <!--: - --> <Item Name="ReSharper Extension Method Identifier" Foreground="0x008812C7" Background="0x02000000" BoldFont="No"/> <Item Name="ReSharper Method Identifier" Foreground="0x008812C7" Background="0x02000000" BoldFont="No"/> <Item Name="ReSharper Operator Identifier" Foreground="0x008812C7" Background="0x02000000" BoldFont="No"/> <!--, , : - --> <Item Name="ReSharper Event Identifier" Foreground="0x001256C7" Background="0x02000000" BoldFont="No"/> <Item Name="ReSharper Field Identifier" Foreground="0x001256C7" Background="0x02000000" BoldFont="No"/> <!--:  --> <Item Name="ReSharper Class Identifier" Foreground="0x00AC8500" Background="0x02000000" BoldFont="No"/> <Item Name="ReSharper Delegate Identifier" Foreground="0x00AC8500" Background="0x02000000" BoldFont="No"/> <Item Name="ReSharper Enum Identifier" Foreground="0x00AC8500" Background="0x02000000" BoldFont="No"/> <Item Name="ReSharper Static Class Identifier" Foreground="0x00AC8500" Background="0x02000000" BoldFont="No"/> <Item Name="ReSharper Interface Identifier" Foreground="0x00AC8500" Background="0x02000000" BoldFont="No"/> <Item Name="ReSharper Struct Identifier" Foreground="0x00AC8500" Background="0x02000000" BoldFont="No"/> <Item Name="ReSharper Type Parameter Identifier" Foreground="0x00AC8500" Background="0x02000000" BoldFont="No"/> <!-- todo  bug. NotImplementedException: --> <Item Name="ReSharper Todo Item" Foreground="0x000000F5" Background="0x02000000" BoldFont="Yes"/> <Item Name="ReSharper Todo Item Marker on Error Stripe" Foreground="0x000000F5" Background="0x02000000" BoldFont="No"/> <!-- string.Format:  + bold--> <Item Name="ReSharper Format String Item" Foreground="0x00AC8500" Background="0x02000000" BoldFont="Yes"/> <!--:  + bold --> <Item Name="ReSharper Constant Identifier" Foreground="0x00004080" Background="0x02000000" BoldFont="Yes"/> </Items> </Category> </Categories> </FontsAndColors> </Category> </Category> </UserSettings>
      
      





比較



例として、いずれかの方法を使用してコードを色付けするための6つのオプションを比較することをお勧めします。 ご存知のように、味と色には同志がいないので、ある種の色が原則として最高であるとは言い切れません。 しかし、私はhabrコミュニティの集合的な意見に興味があります。



1. <source lang = "cs">

 private static string getColor(HtmlNode node){ var attr = node.Attributes["style"]; if (attr == null || attr.Value == null){ return null; } string[] values = attr.Value.Split(new [] {';'}); foreach (string value in values){ const string prefixColor = "color:"; string trimmed = value.Trim(); if (trimmed.StartsWith(prefixColor)){ return trimmed.Remove(0, prefixColor.Length); } } return null; }
      
      





2.黒と白のコード (HabraCodeFormatterで色と太字を拒否して取得)

private static string getColor(HtmlNodeノード){

var attr = node.Attributes ["style"];



if(attr == null || attr.Value == null){

nullを返します。

}



string [] values = attr.Value.Split(new [] {';'});



foreach(値の文字列値){

const string prefixColor = "color:";

トリミングされた文字列= value.Trim();



if(trimmed.StartsWith(prefixColor)){

return trimmed.Remove(0、prefixColor.Length);

}

}



nullを返します。

}





3.http://highlight.hohli.com

private static string getColor HtmlNode node {

var attr = node 属性 [ "スタイル" ] ;



if attr == null || attr。Value == null {

nullを 返し ます

}



string [ ] values = attr 価値 Split new [ ] { ';' } ;



foreach valuesの文字列 {

const string prefixColor = "color:" ;

string trimmed = value トリム ;



if trimmed。StartsWith prefixColor {

トリミングを返し ます。 削除 0 、prefixColor.Length ;

}

}



nullを 返し ます

}


4. Visual Studioの標準カラーリング

プライベート   静的   string getColor( HtmlNode ノード){

     var attr = node.Attributes [ "style" ];

 

     if (attr == null || attr.Value == null ){

         帰る   ヌル

}

 

     string [ ] values = attr.Value.Split( new [] { ';' });

 

     foreach 値の 文字列 値){

         const   string prefixColor = "color:" ;

         トリミングされた 文字列 = value.Trim();

 

         if (trimmed.StartsWith(prefixColor)){

             return trimmed.Remove(0、prefixColor.Length);

         }

}

 

     帰る   ヌル

}



5.標準色のリシェーパー

private static string getColorHtmlNodeノード){

var attr = node。 属性 [ "スタイル" ];



if (attr == null || attr。Value == null ){

nullを 返し ます

}



文字列 []値= attr。 価値 Splitnew [] { ';' });



foreach値の 文字列値){

const string prefixColor = "color:" ;

string trimmed = valueトリム ();



if (トリミングされたStartsWithprefixColor )){

トリミングを返します。 削除 (0、 prefixColor。Length );

}

}



nullを 返し ます

}





6.著者のカラーリング

private static string getColorHtmlNodeノード){

var attr = node。 属性 [ "スタイル" ];



if (attr == null || attr。Value == null ){

nullを 返し ます

}



文字列 []値= attr。 価値 Splitnew [] { ';' });



foreach (値の文字列値){

const string prefixColor = "color:" ;

トリミングされた文字列 =値。 トリム ();



if (トリミングされたStartsWithprefixColor )){

トリミングを返します。 削除0prefixColor。Length );

}

}



nullを 返し ます

}






All Articles