用Markdown改造程序日志

用Markdown改造程序日志

  • 引子
  • 简单思路
  • 开干
    • 开个头
    • 写信息
    • 写阶段标题
    • 颜色控制
    • 图片输出
  • 报告生成
    • 模板文件
    • 网页文件生成
    • 程序中展示
  • 最终网页显示效果

DrGraph QQ:282397369

引子

说起来有点不好意思,也就是上一篇博客的时候用了下Markdown,结果发现这种方式写博客比较轻松。对于我这样的,能编点应用程序,但对网页技术只是了解点皮毛,远谈不上精通的人来说,Markdown比较有用。
毕竟自己看点东西也希望规范一些,网页效果很好,但技术门派太多,也一直没心思去深入研究学习。
有了一篇博客的基础,突然想把自己程序的日志采用Markdown来改造一下。

简单思路

  • 程序在各需要输出日志的时刻把信息写入到日志文本文件中
  • 最终统一生成规范网页日志
  • 没有必要大而全,只需要把关心的格式实现出来就OK

开干

开个头

每次写Markdown文件需要有个目标,用流方式来实现即可。第一次就创建,后续直接打开续写。

TFileStream * __fastcall TDrLUA::GetLogStream() {
	TFileStream * ErrorsLog = NULL;
	UnicodeString LogFile = FStatusXmlFileName;
	try {
		if (FileExists(LogFile)) {
			ErrorsLog = new TFileStream(LogFile, fmOpenReadWrite | fmShareExclusive);
			ErrorsLog->Position = ErrorsLog->Size;
		}
		else {
			ErrorsLog = new TFileStream(LogFile, fmCreate);
			AnsiString info = THelper::FormatString(L"# 脚本日志报告\n- 程序当前版本:%s\n- 程序修改时刻:%s\n",
				TGraphApp::AppVersion, THelper::File::GetFileTimeDesc(Application->ExeName, cftLastWrite));
			ErrorsLog->Write((void*)(info.c_str()), info.Length());
		}
	}
	catch (...) {
		ErrorsLog = NULL;
	}
	return ErrorsLog;
}

这样,后续操作只需要直接操作GetLogStream返回流对象

写信息

准备将信息展现为表格形式,第一列为时刻,第二列为信息。所以加一个小的控制,FStartLogTextFlag

void __fastcall TDrLUA::LogScript_Text(UnicodeString text) {
	TFileStream * fs = GetLogStream();
	if(fs) {
			UnicodeString logInfo = text;
			if(!FStartLogTextFlag) {
				logInfo = THelper::FormatString(L"|时刻|信息|\n|:--|:--|\n|%s|%s|\n",
					TTypeConvert::Moment2String(GetTickCount(), L"hh:nn:ss:zzz"),
					logInfo);
			} else
				logInfo = THelper::FormatString(L"|%s|%s|\n",
					TTypeConvert::Moment2String(GetTickCount(), L"hh:nn:ss:zzz"),
					logInfo);
			AnsiString info = logInfo;
			fs->Write((void*)(info.c_str()), info.Length());
			FStartLogTextFlag = true;
		}
    	delete fs;
	}
}

当然,信息的展现形式,如字体颜色之类的,在调用时按需处理

写阶段标题

日志信息就象是流水账,加上标题就更为脉络清晰一些。直接就加个#即可。目前先只处理一级标题,如果需要多级标题,加一个参数int level应该就足够

void __fastcall TDrLUA::LogScript_Title(UnicodeString text) {
	TFileStream * fs = GetLogStream();
	if(fs) {
		AnsiString info = THelper::FormatString(L"\n---\n# %s\n", text);
		fs->Write((void*)(info.c_str()), info.Length());
		FStartLogTextFlag = false;
   		delete fs;
	}
}

颜色控制

发现需要加上font color=#…才能控制颜色,这个在输出的时候加上即可。

		LogScript_Text(THelper::FormatString(L"&font color=%s;**%s**&font;",
			TTypeConvert::WebColorString(color), info), 0);                        

图片输出

按Markdown图片格式进入输出

void __fastcall TDrLUA::LogScript_Mat(cv::Mat& mat) {
	UnicodeString destPicFileName = THelper::FormatString(L"%s%s.png",
		ExtractFilePath(FStatusXmlFileName), TTypeConvert::Moment2String(GetTickCount(), L"hh_nn_ss_zzz"));
	CvHelper::MatToFile(mat, destPicFileName);
	LogScript_Text(THelper::FormatString(L"&font color=#ff0000;**![警告:返回了空图片](%s \"返回图片\")**&font;", ExtractFileName(destPicFileName)), 0);
}

报告生成

模板文件

在网上搜了一下,直接用shutdown这个JS模块处理。下载到固定文件夹。设计一个样本报告网页文件

<!DOCTYPE html>
<html><head>
	<title>&Title;</title>
	<script type="text/javascript" src="&AppPath;Res\showdown\showdown.js"></script>
</head><body><div id="result"></div>
<script type="text/javascript">
function convert(){	
	var text = "&MarkDownContent;"; 
    var converter = new showdown.Converter();
    var html = converter.makeHtml(text);
    document.getElementById("result").innerHTML = html;
}
window.onload=function(){convert(); }
</script></body>

网页文件生成

在程序生成的时候,相应替换上面文件中&…;即可

		UnicodeString __fastcall THelper::Log::BuildMarkDownReport(UnicodeString markDownFileName, UnicodeString destTitle) {
			UnicodeString templateFileName = THelper::File::GetPath_Application() + L"res\\showdown\\report.html";
			UnicodeString destHtmlFileName = ChangeFileExt(markDownFileName, L".html");
			if(FileExists(destHtmlFileName))
				DeleteFile(destHtmlFileName);
			if(FileExists(templateFileName)) {
				TStrings * lines = new TStringList;
				lines->LoadFromFile(templateFileName, System::Sysutils::TEncoding::UTF8);
				UnicodeString markDownContent = THelper::File::GetFileContent(markDownFileName, false);
				if(markDownContent.Length() == 0)
					markDownContent = THelper::FormatString(L"#文件 '%s' 无内容", ExtractFileName(markDownFileName));
				for(int i = 0; i < lines->Count; ++i) {
					UnicodeString content = lines->Strings[i];
					if(content.Pos(L"&AppPath;"))
						THelper::String::ReplaceStringInStr(content, L"&AppPath;", THelper::File::GetPath_Application());
					else if(content.Pos(L"&MarkDownContent;"))
						THelper::String::ReplaceStringInStr(content, L"&MarkDownContent;", markDownContent);
					else if(content.Pos(L"&Title;"))
						THelper::String::ReplaceStringInStr(content, L"&Title;", destTitle);
					else continue;
					lines->Strings[i] = content;
				}
				lines->SaveToFile(destHtmlFileName, System::Sysutils::TEncoding::UTF8);
				delete lines;
			}
			return destHtmlFileName;
		}

程序中展示

直接用CEF3浏览器显示。

最终网页显示效果

  • 直接在浏览器中打开网页日志文件
    用Markdown改造程序日志_第1张图片
  • 在程序中显示网页日志文件
    用Markdown改造程序日志_第2张图片
    这下感觉清爽多了。

你可能感兴趣的:(用Markdown改造程序日志)