优化Markdown预览工具:临时文件清理与模板应用
立即解锁
发布时间: 2025-09-14 00:07:59 阅读量: 2 订阅数: 38 AIGC 

### 优化Markdown预览工具:临时文件清理与模板应用
在开发命令行工具时,文件操作是一项常见且重要的任务。本文将围绕Markdown预览工具(mdp)的优化展开,主要涉及临时文件清理和模板应用两个方面,同时还会介绍如何利用Go语言的相关特性来解决实际问题。
#### 临时文件清理
当前,我们的程序在创建临时文件后不会自动清理这些文件。多次运行工具会产生不同的临时文件,例如:
```bash
$ go run main.go -file README.md
/tmp/mdp552496404.html
$ go run main.go -file README.md
/tmp/mdp016541878.html
$ ls -ltr /tmp/ | grep mdp
-rw------- 1 ricardo users 503 Apr 15 10:25 mdp807323568.html
-rw------- 1 ricardo users 503 Apr 15 10:27 mdp552496404.html
-rw------- 1 ricardo users 503 Apr 15 10:31 mdp016541878.html
```
为了保持系统的整洁,我们需要手动删除这些临时文件。在Go程序中,可以使用`os.Remove`函数来删除文件,并使用`defer`语句确保在当前函数返回时删除文件。以下是更新后的`run`函数:
```go
func run(filename string, out io.Writer, skipPreview bool) error {
// Read all the data from the input file and check for errors
input, err := ioutil.ReadFile(filename)
if err != nil {
return err
}
htmlData := parseContent(input)
// Create temporary file and check for errors
temp, err := ioutil.TempFile("", "mdp*.html")
if err != nil {
return err
}
if err := temp.Close(); err != nil {
return err
}
outName := temp.Name()
fmt.Fprintln(out, outName)
if err := saveHTML(outName, htmlData); err != nil {
return err
}
if skipPreview {
return nil
}
defer os.Remove(outName)
return preview(outName)
}
```
使用`run`函数的一个好处是可以安全地使用`defer`语句来清理资源,因为它返回一个值,而不是依赖`os.Exit`来退出程序。需要注意的是,使用`os.Exit`会立即退出程序,不会执行任何延迟函数调用。
自动删除文件会引入一个小的竞态条件:浏览器可能没有足够的时间打开文件就被删除了。为了解决这个问题,可以在`preview`函数返回之前添加一个小的延迟,让浏览器有时间打开文件。首先,导入`time`包:
```go
import (
"bytes"
"flag"
"fmt"
"io"
"io/ioutil"
"os"
"os/exec"
"runtime"
"time"
"github.com/microcosm-cc/bluemonday"
"github.com/russross/blackfriday/v2"
)
```
然后,在`preview`函数中添加两秒的延迟:
```go
func preview(fname string) error {
cName := ""
cParams := []string{}
// Define executable based on OS
switch runtime.GOOS {
case "linux":
cName = "xdg-open"
case "windows":
cName = "cmd.exe"
cParams = []string{"/C", "start"}
case "darwin":
cName = "open"
default:
return fmt.Errorf("OS not supported")
}
// Append filename to parameters slice
cParams = append(cParams, fname)
// Locate executable in PATH
cPath, err := exec.LookPath(cName)
if err != nil {
return err
}
// Open the file using default program
err = exec.Command(cPath, cParams...).Run()
// Give the browser some time to open the file before deleting it
time.Sleep(2 * time.Second)
return err
}
```
需要注意的是,添加延迟并不是一个推荐的长期解决方案,这只是一个快速修复方法,以便你可以专注于清理功能。后续可以通过处理信号或创建小型Web服务器来更好地解决这个问题。
执行测试确保所有测试都通过:
```bash
$ go test -v
=== RUN TestParseContent
--- PASS: TestParseContent (0.00s)
=== RUN TestRun
--- PASS: TestRun (0.00s)
PASS
ok pragprog.com/rggo/workingFiles/mdp 0.009s
```
构建并执行新工具,你会发现预览文件会自动在浏览器中打开,并且文件会自动从临时目录中删除。
在Linux/Unix-like系统上,还可以创建一个脚本,在每次更改Markdown文件时自动预览:
```bash
#!/bin/bash
FHASH=`md5sum $1`
while true; do
NHASH=`md5sum $1`
if [ "$NHASH" != "$FHASH" ]; then
./mdp -file $1
FHASH=$NHASH
fi
sleep 5
done
```
将脚本保存为`autopreview.sh`,并使其可执行:
```bas
```
0
0
复制全文
相关推荐









