用 golang 开发 selpg
文章目录
一、代码连接
二、Selpg相关内容
selpg 是从文本输入选择也范围的实用程序。该输入可以来自作为最后一个命令行参数指定的文件,在没有给出文件名参数时也可以来自标准输入
selpg首先要处理所有的命令行参数,在扫描了所有的选项参数(也就是哪些以连字符为前缀的参数后,如果 selpg 还发现有一个参数,则将其作为输入文件的名称并尝试打开它进行读取,如果没有其他参数,则 selpg 假定输入来自标准输入
因此这份代码基本参考上面那份C语言代码
三、参数设置
-
输入格式
selpg [-s 开始读取页号][-e 结束读取页号][-l 一页多少行 | -f ][-d 输出目的地] 文件名
-
必要的参数
-s 后接开始读取的页号(int)
-e 后接结束读取的页号(int)
-
可选的参数
-l 后接行数(int),代表多少行一页,默认72行
-f 表示分页
四、具体代码
1. 引用包
import (
"bufio"
"fmt"
"io"
"os"
"os/exec"
"strings"
flag "github.com/ogier/pflag"
)
2. 数据结构
和 C 语言代码一样,建了一个结构体
type selpgArgs struct {
start_page int
end_page int
page_len int
page_type bool
print_dest string
in_filename string
}
3. main函数
C语言代码里面,main函数设置了各个参数的初始值,在函数 process_args() 里面处理输入,go语言可以通过 flag 来处理输入。
flag.IntVarP(&sa.start_page, "s", "s", -1, "the start page")
flag.IntVarP(&sa.end_page, "e", "e", -1, "the end page")
flag.IntVarP(&sa.page_len, "l", "l", 72, "the paging form")
flag.StringVarP(&sa.print_dest, "d", "d", "", "the printer")
flag.BoolVarP(&sa.page_type, "f", "f", false, "is read by page")
同时由输入格式可以看出,还有一个不带参数的输入是文件名,这个要自行读取存储
if flag.NArg() == 1 {
sa.in_filename = flag.Arg(0)
} else {
sa.in_filename = ""
}
然后就是一个检验输入的函数 handle_args()
和一个执行的函数process_input()
4.handle_args()
第一部分是处理 C 语言代码里面是否存在初始页数大于终止页数,及分别小于1的情况的
if sa.start_page > sa.end_page || sa.start_page < 1 {
usage()
os.Exit(1)
}
第二部分是处理是否有过多的非参数指令的
if notFlagNum != 1 && notFlagNum != 0 {
usage()
os.Exit(1)
}
第三部分是处理是否出现 -f -l xxx 的情况的
if sa.page_type == true {
if sa.page_len != -1 {
usage()
os.Exit(1)
}
}
这里面调用的usage()
函数是输出应该输入的格式,格式在上面有给出
5.process_input()
这里和C语言代码一样,首先处理输入来源
//set the input source
if sa.in_filename != "" {
fin, err = os.Open(sa.in_filename)
if err != nil {
fmt.Fprintf(os.Stderr, "selpg: could not open input file \"%s\"\n", sa.in_filename)
fmt.Println(err)
usage()
os.Exit(1)
}
defer fin.Close()
}
然后处理输出,这里参考了别人的博客
//set the output
fout := os.Stdout
var inpipe io.WriteCloser
if sa.print_dest != "" {
cmd := exec.Command("lp", "-d"+sa.print_dest)
inpipe, err = cmd.StdinPipe()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer inpipe.Close()
cmd.Stdout = fout
cmd.Start()
}
然后分别处理按行读取和按页读取,关于这部分参考了博客:Go如何按行读取文件及bufio.Split()函数的使用