怎样在 Markdown 中使程序代码带上行号
2016-03-16 20:59
513 查看
在图灵社区使用 Markdown 写文章时,如果在一段文字的每行开头加上四个空格,或者一个制表符(Tab),这段文字就会被视为程序代码。这样,就会自动识别所用的编程语言,进行代码染色,语法高亮显示。但是,如果这段程序很长的话,就有两个小问题:
每行的开头要加上空格或制表符,很麻烦。
如果要显示行号的话,就更麻烦了。
因此,我用 C# 语言写了小程序,建设一个 ASP.NET 4 网站来解决上述两个麻烦:
[+]查看原图
在这个网页中:
Line Count 复选框表示是否需要加上行号。
Prefix 中的的 Space 和 Tab 无线按钮让你选择每行开头是增加空格还是制表符。
Prefix Count 文本框让你输入缩进的层次。默认是缩进一层 。但是如果遇到在有序列表或无序列表中的程序代码,就需要缩进两层,甚至更多层了。
这个网站的总体结构如下所示:
网站的配置文件 Web.config 如下所示:
网站的 Web 页面文件 CodeFormat.aspx 如下所示:
以及对应的后台 C# 代码 CodeFormat.aspx.cs:
上述程序中:
第 34 至 39 行的
第 26 至 32 行的
第 29 至 30 行调用
下面就是 CodeFormat 类的源程序代码 CodeFormat.cs:
上述程序中:
第 9 至 10 行的
在这个网站中,是使用
tbxInput 和 tbxOutput 文本框。
如果使用
如果使用
第 23 至 28 行的
第 30 至 38 行的
第 32 行根据
第 33 至 34 行根据
第 34 行的
第 36 至 37 行的循环逐行格式化数据。
最后是 Makefile:
有了上面的源程序后,执行 make 命令编译整个网站:
src$ make
dmcs -out:../bin/CodeFormat.dll -t:library -r:System.Web.dll CodeFormat.aspx.cs CodeFormat.cs
这就大功告成了。
from: http://www.ituring.com.cn/article/35350
每行的开头要加上空格或制表符,很麻烦。
如果要显示行号的话,就更麻烦了。
因此,我用 C# 语言写了小程序,建设一个 ASP.NET 4 网站来解决上述两个麻烦:
[+]查看原图
在这个网页中:
Line Count 复选框表示是否需要加上行号。
Prefix 中的的 Space 和 Tab 无线按钮让你选择每行开头是增加空格还是制表符。
Prefix Count 文本框让你输入缩进的层次。默认是缩进一层 。但是如果遇到在有序列表或无序列表中的程序代码,就需要缩进两层,甚至更多层了。
这个网站的总体结构如下所示:
网站的配置文件 Web.config 如下所示:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <httpRuntime requestValidationMode="2.0" /> <globalization requestEncoding="utf-8" responseEncoding="utf-8" /> </system.web> </configuration>
网站的 Web 页面文件 CodeFormat.aspx 如下所示:
<%@ Page validateRequest="false" Language="C#" inherits="Skyiv.Ben.Web.CodeFormatPage" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Code Format</title> </head> <body> <form id="form1" runat="server"> <asp:Button Onclick="Submit" Text="Submit" Runat="Server" /> <span style="background-color:LightBlue;"> <asp:CheckBox Id="chkLineCount" Text="Line Count" Checked="True" Runat="Server" /> </span> <span style="background-color:LightBlue;"> Prefix: <asp:RadioButton Id="rbnSpace" Text="Space" Checked="True" GroupName="Prefix" Runat="Server" /> <asp:RadioButton Id="rbnTab" Text="Tab" GroupName="Prefix" Runat="Server" /> </span> <span style="background-color:LightBlue;"> Prefix Count: <asp:TextBox Runat="Server" Id="tbxLevel" Text="1" Columns="2" MaxLength="1" /> </span> <hr /> <div> <asp:TextBox Runat="Server" Id="tbxInput" Wrap="False" TextMode="MultiLine" Columns="80" Rows="10" /> <br /> <asp:TextBox Runat="Server" Id="tbxOutput" ReadOnly="True" Wrap="False" TextMode="MultiLine" BackColor="LightBlue" Columns="80" Rows="10" /> </div> </form> </body> </html>
以及对应的后台 C# 代码 CodeFormat.aspx.cs:
1: using System; 2: using System.IO; 3: using System.Web; 4: using System.Web.UI; 5: using System.Web.UI.WebControls; 6: using Skyiv.Utils; 7: 8: namespace Skyiv.Ben.Web 9: { 10: public class CodeFormatPage : Page 11: { 12: protected TextBox tbxInput; 13: protected TextBox tbxOutput; 14: protected TextBox tbxLevel; 15: protected CheckBox chkLineCount; 16: protected RadioButton rbnTab; 17: 18: protected void Page_Load(object sender, EventArgs e) 19: { 20: tbxOutput.Text = string.Format(" OS: {1} ({2}-bit){0}CLR: {3}", 21: Environment.NewLine, Environment.OSVersion, 22: Environment.Is64BitOperatingSystem ? 64 : 32, 23: Environment.Version); 24: } 25: 26: protected void Submit(object sender, EventArgs e) 27: { 28: var writer = new StringWriter(); 29: new CodeFormat(new StringReader(tbxInput.Text), 30: writer).Run(chkLineCount.Checked, rbnTab.Checked, GetLevel(tbxLevel.Text)); 31: tbxOutput.Text = writer.ToString(); 32: } 33: 34: int GetLevel(string str) 35: { 36: int n; 37: if (!int.TryParse(str, out n)) n = 1; 38: return Math.Min(5, Math.Max(0, n)); 39: } 40: } 41: }
上述程序中:
第 34 至 39 行的
GetLevel方法读取 Prefix Count 文本框中的缩进层次,返回结果限制在 0 到 5 之间。
第 26 至 32 行的
Submit方法在 Web 页面中的 Submit 按钮被点击时被调用。
第 29 至 30 行调用
CodeFormat类的
Run方法对程序代码进行格式化(加行号、行首空格等)。
下面就是 CodeFormat 类的源程序代码 CodeFormat.cs:
1: using System; 2: using System.IO; 3: using System.Collections.Generic; 4: 5: namespace Skyiv.Utils 6: { 7: sealed class CodeFormat 8: { 9: TextReader reader; 10: TextWriter writer; 11: 12: public CodeFormat(TextReader reader, TextWriter writer) 13: { 14: this.reader = reader; 15: this.writer = writer; 16: } 17: 18: public void Run(bool hasCount, bool isTab, int level) 19: { 20: Write(Read(), hasCount, isTab, level); 21: } 22: 23: List<string> Read() 24: { 25: var lines = new List<string>(); 26: for (string s; (s = reader.ReadLine()) != null; ) lines.Add(s); 27: return lines; 28: } 29: 30: void Write(List<string> lines, bool hasCount, bool isTab, int level) 31: { 32: var prefix = "".PadLeft((isTab ? 1 : 4) * level, isTab ? '\t' : ' '); 33: var format = "{0}" + (hasCount ? "{1," + 34: lines.Count.ToString().Length + "}: " : "") + "{2}"; 35: var count = 0; 36: foreach (var line in lines) 37: writer.WriteLine(format, prefix, ++count, line); 38: } 39: } 40: }
上述程序中:
第 9 至 10 行的
TextReader和
TextWriter分别用于读取数据和输出格式化后的结果,这两个类是抽象基类。
在这个网站中,是使用
StringReader和
StringWriter派生类,对应于 Web 页面的
tbxInput 和 tbxOutput 文本框。
如果使用
StreamReader和
StreamWriter派生类,就可以从输入流读取数据,写到输出流中。
如果使用
Console.In和
Console.Out,就可以从标准输入读取数据,写到标准输出。
第 23 至 28 行的
Read方法读取数据到内存的
List<string>数据结构中。
第 30 至 38 行的
Writer方法将内存中的数据格式化后写出去。
第 32 行根据
isTab和
level参数决定程序代码数据每行的前缀。
第 33 至 34 行根据
hasCount参数决定行号的内容。
第 34 行的
lines.Count.ToString().Length是行号所占的宽度。
第 36 至 37 行的循环逐行格式化数据。
最后是 Makefile:
CSC = dmcs DLL1 = -r:System.Web.dll ../bin/CodeFormat.dll: CodeFormat.aspx.cs CodeFormat.cs $(CSC) -out:$@ -t:library $(DLL1) CodeFormat.aspx.cs CodeFormat.cs
有了上面的源程序后,执行 make 命令编译整个网站:
src$ make
dmcs -out:../bin/CodeFormat.dll -t:library -r:System.Web.dll CodeFormat.aspx.cs CodeFormat.cs
这就大功告成了。
from: http://www.ituring.com.cn/article/35350