From 47716aa55b91f9e02466bcc762365f1e4763a8a1 Mon Sep 17 00:00:00 2001
From: yesAnd <850208971@qq.com>
Date: Wed, 3 Apr 2024 16:35:41 +0800
Subject: [PATCH 1/6] add env command
---
cmd/env.go | 30 +++++++++++
cmd/root.go | 1 +
handler/env/env_variable.go | 85 ++++++++++++++++++++++++++++++++
handler/env/env_variable_test.go | 10 ++++
utils/cmderutils.go | 3 +-
utils/osutils.go | 28 +++++++++++
utils/osutils_test.go | 7 +++
7 files changed, 162 insertions(+), 2 deletions(-)
create mode 100644 cmd/env.go
create mode 100644 handler/env/env_variable.go
create mode 100644 handler/env/env_variable_test.go
create mode 100644 utils/osutils.go
create mode 100644 utils/osutils_test.go
diff --git a/cmd/env.go b/cmd/env.go
new file mode 100644
index 0000000..65945b3
--- /dev/null
+++ b/cmd/env.go
@@ -0,0 +1,30 @@
+package cmd
+
+import (
+ "fmt"
+ "github.com/spf13/cobra"
+ "github.com/yesAnd92/lwe/handler/env"
+ "github.com/yesAnd92/lwe/utils"
+)
+
+var envCmd = &cobra.Command{
+ Use: `env`,
+ Short: `Print all environment variable `,
+ Long: `Print all environment variable`,
+ Example: `lwe env`,
+ Args: cobra.MatchAll(cobra.ExactArgs(0)),
+ Run: func(cmd *cobra.Command, args []string) {
+
+ var envV env.IEnvVariable
+ op := utils.OsEnv()
+ fmt.Println("op:", op)
+ switch op {
+ case utils.Mac:
+ envV = &env.MacEVnVariable{}
+ default:
+ cobra.CheckErr("Not support this os!")
+ }
+ envInfos := envV.FindEnvInfo()
+ env.EnvCat(envInfos)
+ },
+}
diff --git a/cmd/root.go b/cmd/root.go
index cd4126d..805cb98 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -50,5 +50,6 @@ func init() {
rootCmd.AddCommand(fsyncCmd)
rootCmd.AddCommand(pdfMergeCmd)
rootCmd.AddCommand(pdfCutCmd)
+ rootCmd.AddCommand(envCmd)
}
diff --git a/handler/env/env_variable.go b/handler/env/env_variable.go
new file mode 100644
index 0000000..1655d68
--- /dev/null
+++ b/handler/env/env_variable.go
@@ -0,0 +1,85 @@
+package env
+
+import (
+ "fmt"
+ "github.com/yesAnd92/lwe/utils"
+ "strings"
+ "time"
+)
+
+type EnvInfo struct {
+ Path string
+ envItems []string
+}
+
+// MacEvnPath MAC env variable file
+var MacEvnPath = []string{
+ "~/.bash_profile", "~/.zshrc", "~/.bashrc"}
+
+// LinuxEvnPath linux env variable file
+var LinuxEvnPath = []string{
+ "~/.zshrc", "~/.bashrc", "/etc/environment"}
+
+type AbstractEnvV struct {
+}
+
+func EnvCat(envInfos []*EnvInfo) {
+ for _, info := range envInfos {
+ fmt.Printf("%s >>>\n", info.Path)
+ for _, item := range info.envItems {
+ fmt.Println(item)
+ }
+
+ fmt.Printf("\n\n")
+ }
+}
+
+type IEnvVariable interface {
+ FindEnvInfo() []*EnvInfo
+}
+
+type WinEVnVariable struct {
+}
+
+func (w *WinEVnVariable) FindEnvInfo() []*EnvInfo {
+
+ //TODO implement me
+ panic("implement me")
+}
+
+type MacEVnVariable struct {
+}
+
+func (m *MacEVnVariable) FindEnvInfo() (envInfos []*EnvInfo) {
+
+ for _, path := range MacEvnPath {
+ cmd := fmt.Sprintf("cat %s", path)
+ result := utils.RunCmd(cmd, 2*time.Second)
+ if result.Err() != nil {
+ continue
+ }
+
+ var envItems []string
+ envLineSplit := strings.Split(result.String(), "\n")
+ for _, envLine := range envLineSplit {
+ envLine = strings.TrimSpace(envLine)
+ // filter comment line
+ if strings.HasPrefix(envLine, "#") || len(envLine) == 0 {
+ continue
+ }
+ envItems = append(envItems, envLine)
+
+ }
+
+ if len(envItems) == 0 {
+ continue
+ }
+ envInfos = append(envInfos, &EnvInfo{
+ Path: path,
+ envItems: envItems,
+ })
+
+ }
+
+ return
+}
diff --git a/handler/env/env_variable_test.go b/handler/env/env_variable_test.go
new file mode 100644
index 0000000..f40399c
--- /dev/null
+++ b/handler/env/env_variable_test.go
@@ -0,0 +1,10 @@
+package env
+
+import (
+ "testing"
+)
+
+func TestMacEVnVariable_findEnvInfo(t *testing.T) {
+ mac := &MacEVnVariable{}
+ mac.FindEnvInfo()
+}
diff --git a/utils/cmderutils.go b/utils/cmderutils.go
index 84a9734..17dabb2 100644
--- a/utils/cmderutils.go
+++ b/utils/cmderutils.go
@@ -6,7 +6,6 @@ import (
"fmt"
"os"
"os/exec"
- "runtime"
"time"
"unsafe"
)
@@ -20,7 +19,7 @@ var cmdArg = make([]string, 2)
// 根据操作系统环境初始化cmd关闭命令行的参数
func init() {
- if runtime.GOOS == "windows" {
+ if OsEnv() == Win {
cmdArg[0] = "cmd"
cmdArg[1] = "/c"
} else {
diff --git a/utils/osutils.go b/utils/osutils.go
new file mode 100644
index 0000000..075474d
--- /dev/null
+++ b/utils/osutils.go
@@ -0,0 +1,28 @@
+package utils
+
+import (
+ "runtime"
+)
+
+type OsPlatform int
+
+const (
+ Other OsPlatform = iota
+ Win
+ Mac
+ Linux
+)
+
+func OsEnv() OsPlatform {
+ // get runtime op platform
+ op := runtime.GOOS
+
+ if op == "windows" {
+ return Win
+ } else if op == "darwin" {
+ return Mac
+ } else if op == "linux" {
+ return Linux
+ }
+ return Other
+}
diff --git a/utils/osutils_test.go b/utils/osutils_test.go
new file mode 100644
index 0000000..9204653
--- /dev/null
+++ b/utils/osutils_test.go
@@ -0,0 +1,7 @@
+package utils
+
+import "testing"
+
+func TestOsEnv(t *testing.T) {
+ println(OsEnv())
+}
From 5dfc9cb02521ed1c9de1ce3e46122234d1c18abf Mon Sep 17 00:00:00 2001
From: yesAnd <850208971@qq.com>
Date: Wed, 3 Apr 2024 17:23:56 +0800
Subject: [PATCH 2/6] add en readme.md
---
README.md | 1 +
README.zh-CN.md | 193 ++++++++++++++++++++++++++++++++++++++++++++++++
tmp.md | 143 +++++++++++++++++++++++++++++++++++
3 files changed, 337 insertions(+)
create mode 100644 README.zh-CN.md
create mode 100644 tmp.md
diff --git a/README.md b/README.md
index d6c1d19..d7ef4b3 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,4 @@
+**[中文文档](README.zh-CN.md)**
## lwe
lwe是leave work early的缩写,也就是"早点下班"!🤣🤣🤣
它是一个帮助开发者提高工作效率的跨平台命令行工具,当然你把它当做go入门学习的项目也是合适的!
diff --git a/README.zh-CN.md b/README.zh-CN.md
new file mode 100644
index 0000000..d6c1d19
--- /dev/null
+++ b/README.zh-CN.md
@@ -0,0 +1,193 @@
+## lwe
+lwe是leave work early的缩写,也就是"早点下班"!🤣🤣🤣
+它是一个帮助开发者提高工作效率的跨平台命令行工具,当然你把它当做go入门学习的项目也是合适的!
+总之,欢迎提issue、提好玩或者使用的功能需求,最好能直接PR参与到项目中,大家一起努力,争取早点下班!!! 💪💪💪
+
+
+## 功能
+
+[Git增强多仓库操作能力:glog、gl、gcl、gst](#git)
+
+[由建表SQL语句转换成Java Bean、Go结构体、Json等](#fmt)
+
+[将SQL语句转换成ElasticSearch查询的DSL语言](#es)
+
+[PDF工具:合并多个图片或者PDF、截取PDF指定页](#pdf)
+
+[其它小工具](#other)
+- 获取Navicat连接配置中的密码
+- 同步两个目录下文件
+- 格式化请求url
+
+
+## 安装
+### 下载编译后的可执行文件
+
+到[release](https://github.com/yesAnd92/lwe/releases)页获取对应平台的版本,在终端上即可使用该二进制文件!
+
+当然,更推荐的方式是将二进制文件配置到环境变量中,这样可以随时随地使用二进制文件
+
+更多的安装方式和注意事项,查查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/0.%E5%AE%89%E8%A3%85%E3%80%81%E9%85%8D%E7%BD%AE%E4%BD%BF%E7%94%A8)
+
+
+
+## 使用
+
+你可以输入`lwe` 查看lwe命令的使用方式,有哪些子命令及其各自对的功能描述。
+
+如果对某个子命令感兴趣,可以使用`-h`参数查看命令的使用示例 ,如:`lwe glog -h`
+
+
+
Git增强多仓库操作能力:glog、gl、gcl、gst
+这里是几个围绕git相关的增强命令,基本都是在原语义上增加了一些跨git仓库的操作
+
+Git增强功能详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/3.Git%E5%A2%9E%E5%BC%BA%E5%8A%9F%E8%83%BD)
+
+#### glog 增强Git日志功能
+查看给定目录下所有git仓库提交日志
+开发人员通常会在多个git仓库下工作,经常会有同时查看多个git仓库提交日志的需求,glog子命令就派上用场了。
+
+使用方式:
+
+```text
+lwe glog [git repo dir] [-a=yesAnd] [-n=50] [-s=2023-08-04] [-e=2023-08-04]
+```
+
+
+#### gl 增强拉取代码功能
+拉取给定目录下的所有git仓库最新代码(使用的git pull --rebase的方式)
+
+
+
+使用方式:
+```text
+lwe gl [git repo dir]
+```
+
+#### gcl 增强git clone功能
+使用方式:
+```text
+lwe gcl gitGroupUrl [dir for this git group] -t=yourToken
+```
+
+#### gst 查看指定目录下所有git仓库状态
+查看给定目录下的所有git仓库状态
+
+使用方式:
+```text
+lwe gst [your git repo dir]
+```
+***
+
+建表语句生成Java Bean实体、Go 结构体等
+
+如果我们已经有了表结构,使用建表语句生成对应的实体可以大大减少我们"无脑且重复"工作。
+目前支持生成的结构包括Java、Go、Json。
+
+使用方式:
+
+```text
+lwe fmt sql-file-path [-t=java|go|json] [-a=yesAnd]
+```
+详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/1.%E5%BB%BA%E8%A1%A8SQL%E8%AF%AD%E5%8F%A5%E7%94%9F%E6%88%90%E4%B8%8D%E7%94%A8%E8%AF%AD%E8%A8%80%E6%89%80%E9%9C%80%E5%AE%9E%E4%BD%93)
+
+***
+
+SQL语句生成DSL语句
+
+```bash
+lwe es [可选参数]
+```
+
+这个命令可以帮我们从繁琐的ES查询语法中解脱出来,它可以将sql语句转换成响应的DSL,并且以curl命令的形式输出,这样服务器上也可以方便的使用。
+当前版本支持的SQL操作
+
+使用方式:
+
+```text
+lwe es 'select * from user where age >18' [-p=true]
+```
+详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/2.%E5%B0%86SQL%E8%AF%AD%E5%8F%A5%E8%BD%AC%E6%8D%A2%E6%88%90ElasticSearch%E6%9F%A5%E8%AF%A2%E7%9A%84DSL%E8%AF%AD%E8%A8%80)
+
+***
+
+PDF工具:合并多个图片或者PDF、截取PDF指定页
+
+对PDF进行简单的编辑还是挺常用的功能,比如把几个PDF、图片合并成一个PDF,从一个PDF中抽离出指定页等,但是在很多办公软件上收费的功能,lwe提供了简单编辑PDF的能力。
+
+#### pdfm 合并PDF或者图片
+按照指定的文件顺序,将多个PDF、图片文件合并成一个PDF文件
+
+使用方式:
+```text
+lwe pdfm out.pdf in1.pdf,in2.jpg,*.png,in3.pdf ...
+```
+详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/PDF%E5%B7%A5%E5%85%B7%EF%BC%9A%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AA%E5%9B%BE%E7%89%87%E6%88%96%E8%80%85PDF%E3%80%81%E6%88%AA%E5%8F%96PDF%E6%8C%87%E5%AE%9A%E9%A1%B5#pdfm-%E5%90%88%E5%B9%B6pdf%E6%88%96%E8%80%85%E5%9B%BE%E7%89%87)
+
+
+#### pdfc 从PDF中截取指定的页
+按照指定的页码,从PDF中截取对应的页生成PDF文件
+
+使用方式:
+```text
+lwe pdfc [-m] in.pdf outDir 2,3,5,7-9,15 ...
+```
+详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/PDF%E5%B7%A5%E5%85%B7%EF%BC%9A%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AA%E5%9B%BE%E7%89%87%E6%88%96%E8%80%85PDF%E3%80%81%E6%88%AA%E5%8F%96PDF%E6%8C%87%E5%AE%9A%E9%A1%B5#pdfc-%E4%BB%8Epdf%E4%B8%AD%E6%88%AA%E5%8F%96%E6%8C%87%E5%AE%9A%E7%9A%84%E9%A1%B5)
+
+***
+
+其它小工具
+一些非常实用的功能
+
+格式化请求url
+有时请求的url很长,不利于我们找到目标参数,可以使用url命令进行格式化,增加请求的可读性
+
+使用方式:
+
+```text
+lwe url yourUrl
+```
+详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/%E5%85%B6%E5%AE%83%E5%B0%8F%E5%B7%A5%E5%85%B7#%E6%A0%BC%E5%BC%8F%E5%8C%96%E8%AF%B7%E6%B1%82url)
+
+
+获取Navicat连接配置中的密码
+如果想从Navicat保存的连接中获取对应数据库的用户名/密码,可以使用ncx文件,ncx文件是Navicat导出的连接配置文件,但ncx中的密码是一个加密后的十六进制串,使用ncx命令可以获取对应的明文
+
+使用方式:
+
+```text
+lwe ncx ncx-file-path
+```
+详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/%E5%85%B6%E5%AE%83%E5%B0%8F%E5%B7%A5%E5%85%B7#%E8%8E%B7%E5%8F%96navicat%E8%BF%9E%E6%8E%A5%E9%85%8D%E7%BD%AE%E4%B8%AD%E7%9A%84%E5%AF%86%E7%A0%81)
+
+同步两个目录下文件
+如果你有备份文件的习惯,这个工具可能会帮到你,它可以将源目录文件下的新增的文件同步到备份目录,省去了你逐层文件夹逐个文件去手动同步。
+
+使用方式:
+```text
+lwe fsync sourceDir targetDir [-d=true]
+```
+
+详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/%E5%85%B6%E5%AE%83%E5%B0%8F%E5%B7%A5%E5%85%B7#%E5%90%8C%E6%AD%A5%E4%B8%A4%E4%B8%AA%E7%9B%AE%E5%BD%95%E4%B8%8B%E6%96%87%E4%BB%B6)
+
+
+
+## 声明
+1.使用[spf13/cobra](github.com/spf13/cobra)库来方便的构建命令行工具
+
+2.es子命令实现借助了[sqlparser](github.com/xwb1989/sqlparser)库来解析SQL语句,一个库很优秀的解析SQL库
+
+3.sql转换成dsl,曹大的[elasticsql](https://github.com/cch123/elasticsql)项目已经是一个很成熟好用的轮子了,lwe也大量借鉴了它的实现思路;没直接调用这个库的原因是想自己练手,同时后续增减功能也更加灵活
+
+4.git增强命令结果输出时使用了[go-pretty](https://github.com/jedib0t/go-pretty)库来表格化提交信息
+
+5.pdf命令是在[pdfcpu](https://github.com/pdfcpu/pdfcpu)基础上进行的封装
+
+## RoadMap
+- fmt 根据需求支持更多类型的转换
+- es 按需增加对insert、update、delete
+ ......
+
+## 开源协议
+
+[MIT License](https://github.com/yesAnd92/lwe/blob/main/LICENSE)
diff --git a/tmp.md b/tmp.md
new file mode 100644
index 0000000..4947a39
--- /dev/null
+++ b/tmp.md
@@ -0,0 +1,143 @@
+**[中文文档](README.zh-CN.md)**
+
+## lwe
+LWE stands for "Leave Work Early," which is a lighthearted way of saying "finish work early"! 🤣🤣🤣
+It is a cross-platform command-line tool designed to help developers increase work efficiency. Of course, it's also suitable for those who want to use it as a project to learn Go!
+
+In short, feel free to submit issues, fun features, or usage feedback. It would be even better if you could directly participate in the project through Pull Requests. Let's all work together and strive for an early finish!!! 💪💪💪
+
+## Features
+- [Enhanced Git operations for multiple repositories: glog, gl, gcl, gst](#git)
+- Conversion from SQL statements to Java Beans, Go structures, JSON, etc.
+- Transformation of SQL statements into ElasticSearch query DSL language
+- PDF tools: merging multiple images or PDFs, extracting specific pages from PDFs
+- Other small tools
+- Retrieving passwords from Navicat connection configurations
+- Synchronizing files between two directories
+- Formatting request URLs
+
+## Installation
+Download the compiled executable files from the release page to use the binary on your platform!
+
+However, a more recommended approach is to configure the binary file to your environment variables, allowing you to use it anytime, anywhere.
+
+For more installation methods and notes, please refer to the Wiki.
+
+## Usage
+You can input `lwe` to view the usage of the LWE commands, including the subcommands and their respective functionality descriptions.
+
+If you're interested in a specific subcommand, you can use the `-h` flag to see usage examples, such as `lwe glog -h`.
+
+Git Enhanced Operations for Multiple Repositories: glog, gl, gcl, gst
+Here are several enhanced commands centered around Git, essentially adding cross-repository operations to the original semantics.
+
+For detailed usage of Git enhanced features, please refer to the Wiki.
+
+#### glog: Enhances Git log functionality
+ It allows you to view the commit logs of all Git repositories in a given directory. Developers often work on multiple Git repositories and may need to check the commit logs of several repositories at the same time. The `glog` subcommand comes in handy for such scenarios.
+
+ usage:
+ ```
+ lwe glog [git repo dir] [-a=yesAnd] [-n=50] [-s=2023-08-04] [-e=2023-08-04]
+ ```
+
+- **gl**: Enhances the code pulling feature
+ Pulls the latest code from all Git repositories in a given directory (using `git pull --rebase`).
+
+ usage:
+ ```
+ lwe gl [git repo dir]
+ ```
+
+- **gcl**: Enhances the `git clone` feature
+ usage:
+ ```
+ lwe gcl gitGroupUrl [dir for this git group] -t=yourToken
+ ```
+
+- **gst**: Views the status of all Git repositories in a specified directory
+ usage:
+ ```
+ lwe gst [your git repo dir]
+ ```
+
+**SQL Statement Generation of Java Bean Entities, Go Structures, etc.**
+If we already have a table structure, generating corresponding entities from the table creation statements can greatly reduce "mindless and repetitive" work. Currently supported structures include Java, Go, and JSON.
+
+usage:
+ ```
+ lwe fmt sql-file-path [-t=java|go|json] [-a=yesAnd]
+ ```
+
+For detailed usage instructions, please refer to the Wiki.
+
+**SQL Statement Generation of DSL Statements**
+`lwe es [optional parameters] `
+
+This command helps us escape the tedious ES query syntax by converting SQL statements into the corresponding DSL and outputting them in the form of curl commands, making it convenient for use on servers as well.
+
+Supported SQL operations in the current version:
+```
+lwe es 'select * from user where age >18' [-p=true]
+```
+
+For detailed usage instructions, please refer to the Wiki.
+
+**PDF Tools: Merging Multiple Images or PDFs, Extracting Specific Pages from PDFs**
+Simple editing of PDFs is a rather common feature, such as merging several PDFs or images into one, or extracting specific pages from a PDF. While this is a paid feature in many office software, LWE provides the capability for simple PDF editing.
+
+- **pdfm**: Merge PDFs or images
+ Combines multiple PDF or image files into a single PDF file in a specified order.
+ usage:
+ ```
+ lwe pdfm out.pdf in1.pdf,in2.jpg,*.png,in3.pdf ...
+ ```
+
+- **pdfc**: Extract specified pages from a PDF
+ Extracts corresponding pages from a PDF and generates a PDF file based on specified page numbers.
+ usage:
+ ```
+ lwe pdfc [-m] in.pdf outDir 2,3,5,7-9,15 ...
+ ```
+
+For detailed usage instructions, please refer to the Wiki.
+
+**Other Small Tools**
+Some very practical features:
+- Formatting request URLs
+ Sometimes the URL for a request can be very long, making it difficult to find the target parameters. The `url` command can be used to format the URL, increasing the readability of the request.
+ usage:
+ ```
+ lwe url yourUrl
+ ```
+
+- Retrieving passwords from Navicat connection configurations
+ If you want to retrieve the username/password for a corresponding database from a connection saved in Navicat, you can use the `ncx` file. The `ncx` file is a connection configuration file exported by Navicat, but the password in the `ncx` file is an encrypted hexadecimal string. The `ncx` command can retrieve the corresponding plaintext.
+ usage:
+ ```
+ lwe ncx ncx-file-path
+ ```
+
+- Synchronizing files between two directories
+ If you have a habit of backing up files, this tool might help you. It can synchronize newly added files from the source directory to the backup directory, saving you the trouble of manually syncing each folder and file one by one.
+ usage:
+ ```
+ lwe fsync sourceDir targetDir [-d=true]
+ ```
+
+For detailed usage instructions, please refer to the Wiki.
+
+**Disclaimer**
+1. The spf13/cobra library is used to conveniently build command-line tools.
+2. The implementation of the `es` subcommand relies on the sqlparser library to parse SQL statements, which is an excellent library for SQL parsing.
+3. The conversion from SQL to DSL heavily borrows from the elasticsql project by Cao Da, which is already a mature and easy-to-use tool. The reason for not directly using this library is to practice on our own and to have more flexibility in adding or removing features later.
+4. The output of Git enhanced command results uses the go-pretty library to tabulate commit information.
+5. The PDF commands are encapsulated based on pdfcpu.
+
+**RoadMap**
+- `fmt`: Support more types of conversions as needed.
+- `es`: Add support for insert, update, delete operations as required.
+- ...
+
+**Open Source License**
+MIT License
From d3d150b76e5f3a5a26ba9c58978407b94d3d0e36 Mon Sep 17 00:00:00 2001
From: yesAnd <850208971@qq.com>
Date: Tue, 7 May 2024 17:25:56 +0800
Subject: [PATCH 3/6] =?UTF-8?q?=E8=B0=83=E6=95=B4=20=E8=8B=B1=E6=96=87READ?=
=?UTF-8?q?ME=E6=A0=BC=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
tmp.md | 44 ++++++++++++++++++++++++--------------------
1 file changed, 24 insertions(+), 20 deletions(-)
diff --git a/tmp.md b/tmp.md
index 4947a39..c83218e 100644
--- a/tmp.md
+++ b/tmp.md
@@ -7,11 +7,15 @@ It is a cross-platform command-line tool designed to help developers increase wo
In short, feel free to submit issues, fun features, or usage feedback. It would be even better if you could directly participate in the project through Pull Requests. Let's all work together and strive for an early finish!!! 💪💪💪
## Features
-- [Enhanced Git operations for multiple repositories: glog, gl, gcl, gst](#git)
-- Conversion from SQL statements to Java Beans, Go structures, JSON, etc.
-- Transformation of SQL statements into ElasticSearch query DSL language
-- PDF tools: merging multiple images or PDFs, extracting specific pages from PDFs
-- Other small tools
+[Enhanced Git operations for multiple repositories: glog, gl, gcl, gst](#git)
+
+[Conversion from SQL statements to Java Beans, Go structures, JSON, etc.](#fmt)
+
+[Transformation of SQL statements into ElasticSearch query DSL language](#es)
+
+[PDF tools: merging multiple images or PDFs, extracting specific pages from PDFs](#pdf)
+
+[Other small tools](#other)
- Retrieving passwords from Navicat connection configurations
- Synchronizing files between two directories
- Formatting request URLs
@@ -41,7 +45,7 @@ For detailed usage of Git enhanced features, please refer to the Wiki.
lwe glog [git repo dir] [-a=yesAnd] [-n=50] [-s=2023-08-04] [-e=2023-08-04]
```
-- **gl**: Enhances the code pulling feature
+#### gl: Enhances the code pulling feature
Pulls the latest code from all Git repositories in a given directory (using `git pull --rebase`).
usage:
@@ -49,19 +53,19 @@ For detailed usage of Git enhanced features, please refer to the Wiki.
lwe gl [git repo dir]
```
-- **gcl**: Enhances the `git clone` feature
+#### gcl: Enhances the `git clone` feature
usage:
```
lwe gcl gitGroupUrl [dir for this git group] -t=yourToken
```
-- **gst**: Views the status of all Git repositories in a specified directory
+#### gst: Views the status of all Git repositories in a specified directory
usage:
```
lwe gst [your git repo dir]
```
-**SQL Statement Generation of Java Bean Entities, Go Structures, etc.**
+SQL Statement Generation of Java Bean Entities, Go Structures, etc.
If we already have a table structure, generating corresponding entities from the table creation statements can greatly reduce "mindless and repetitive" work. Currently supported structures include Java, Go, and JSON.
usage:
@@ -71,7 +75,7 @@ usage:
For detailed usage instructions, please refer to the Wiki.
-**SQL Statement Generation of DSL Statements**
+SQL Statement Generation of DSL Statements
`lwe es [optional parameters] `
This command helps us escape the tedious ES query syntax by converting SQL statements into the corresponding DSL and outputting them in the form of curl commands, making it convenient for use on servers as well.
@@ -83,17 +87,17 @@ lwe es 'select * from user where age >18' [-p=true]
For detailed usage instructions, please refer to the Wiki.
-**PDF Tools: Merging Multiple Images or PDFs, Extracting Specific Pages from PDFs**
+PDF Tools: Merging Multiple Images or PDFs, Extracting Specific Pages from PDFs
Simple editing of PDFs is a rather common feature, such as merging several PDFs or images into one, or extracting specific pages from a PDF. While this is a paid feature in many office software, LWE provides the capability for simple PDF editing.
-- **pdfm**: Merge PDFs or images
+#### pdfm: Merge PDFs or images
Combines multiple PDF or image files into a single PDF file in a specified order.
usage:
```
lwe pdfm out.pdf in1.pdf,in2.jpg,*.png,in3.pdf ...
```
-- **pdfc**: Extract specified pages from a PDF
+#### pdfc: Extract specified pages from a PDF
Extracts corresponding pages from a PDF and generates a PDF file based on specified page numbers.
usage:
```
@@ -102,23 +106,23 @@ Simple editing of PDFs is a rather common feature, such as merging several PDFs
For detailed usage instructions, please refer to the Wiki.
-**Other Small Tools**
+Other Small Tools
Some very practical features:
-- Formatting request URLs
+ Formatting request URLs
Sometimes the URL for a request can be very long, making it difficult to find the target parameters. The `url` command can be used to format the URL, increasing the readability of the request.
usage:
```
lwe url yourUrl
```
-- Retrieving passwords from Navicat connection configurations
+ Retrieving passwords from Navicat connection configurations
If you want to retrieve the username/password for a corresponding database from a connection saved in Navicat, you can use the `ncx` file. The `ncx` file is a connection configuration file exported by Navicat, but the password in the `ncx` file is an encrypted hexadecimal string. The `ncx` command can retrieve the corresponding plaintext.
usage:
```
lwe ncx ncx-file-path
```
-- Synchronizing files between two directories
+ Synchronizing files between two directories
If you have a habit of backing up files, this tool might help you. It can synchronize newly added files from the source directory to the backup directory, saving you the trouble of manually syncing each folder and file one by one.
usage:
```
@@ -127,17 +131,17 @@ Some very practical features:
For detailed usage instructions, please refer to the Wiki.
-**Disclaimer**
+## Disclaimer
1. The spf13/cobra library is used to conveniently build command-line tools.
2. The implementation of the `es` subcommand relies on the sqlparser library to parse SQL statements, which is an excellent library for SQL parsing.
3. The conversion from SQL to DSL heavily borrows from the elasticsql project by Cao Da, which is already a mature and easy-to-use tool. The reason for not directly using this library is to practice on our own and to have more flexibility in adding or removing features later.
4. The output of Git enhanced command results uses the go-pretty library to tabulate commit information.
5. The PDF commands are encapsulated based on pdfcpu.
-**RoadMap**
+## RoadMap
- `fmt`: Support more types of conversions as needed.
- `es`: Add support for insert, update, delete operations as required.
- ...
-**Open Source License**
+## Open Source License
MIT License
From 207a6474119b0b8a26e5a40bd3bdfef1e89cef9c Mon Sep 17 00:00:00 2001
From: yesAnd <850208971@qq.com>
Date: Mon, 3 Jun 2024 17:17:25 +0800
Subject: [PATCH 4/6] complete en readme.md
---
tmp.md => README.EN.md | 62 +++++++------
README.md | 2 +-
README.zh-CN.md | 193 -----------------------------------------
3 files changed, 37 insertions(+), 220 deletions(-)
rename tmp.md => README.EN.md (67%)
delete mode 100644 README.zh-CN.md
diff --git a/tmp.md b/README.EN.md
similarity index 67%
rename from tmp.md
rename to README.EN.md
index c83218e..a27d284 100644
--- a/tmp.md
+++ b/README.EN.md
@@ -1,4 +1,4 @@
-**[中文文档](README.zh-CN.md)**
+**[中文文档](README.md)**
## lwe
LWE stands for "Leave Work Early," which is a lighthearted way of saying "finish work early"! 🤣🤣🤣
@@ -7,6 +7,7 @@ It is a cross-platform command-line tool designed to help developers increase wo
In short, feel free to submit issues, fun features, or usage feedback. It would be even better if you could directly participate in the project through Pull Requests. Let's all work together and strive for an early finish!!! 💪💪💪
## Features
+
[Enhanced Git operations for multiple repositories: glog, gl, gcl, gst](#git)
[Conversion from SQL statements to Java Beans, Go structures, JSON, etc.](#fmt)
@@ -15,17 +16,18 @@ In short, feel free to submit issues, fun features, or usage feedback. It would
[PDF tools: merging multiple images or PDFs, extracting specific pages from PDFs](#pdf)
-[Other small tools](#other)
+[Other utilities](#other)
- Retrieving passwords from Navicat connection configurations
- Synchronizing files between two directories
- Formatting request URLs
## Installation
-Download the compiled executable files from the release page to use the binary on your platform!
-However, a more recommended approach is to configure the binary file to your environment variables, allowing you to use it anytime, anywhere.
+Download the compiled executable files from the [release](https://github.com/yesAnd92/lwe/releases)
+
+Usually,the more recommended approach is to configure the binary file to your environment variables, allowing you to use it anytime, anywhere.
-For more installation methods and notes, please refer to the Wiki.
+For more installation methods and notes, please refer to the [Wiki](https://github.com/yesAnd92/lwe/wiki/0.%E5%AE%89%E8%A3%85%E3%80%81%E9%85%8D%E7%BD%AE%E4%BD%BF%E7%94%A8)
## Usage
You can input `lwe` to view the usage of the LWE commands, including the subcommands and their respective functionality descriptions.
@@ -35,32 +37,32 @@ If you're interested in a specific subcommand, you can use the `-h` flag to see
Git Enhanced Operations for Multiple Repositories: glog, gl, gcl, gst
Here are several enhanced commands centered around Git, essentially adding cross-repository operations to the original semantics.
-For detailed usage of Git enhanced features, please refer to the Wiki.
+For detailed usage of Git enhanced features, please refer to the [Wiki](https://github.com/yesAnd92/lwe/wiki/3.Git%E5%A2%9E%E5%BC%BA%E5%8A%9F%E8%83%BD)
#### glog: Enhances Git log functionality
- It allows you to view the commit logs of all Git repositories in a given directory. Developers often work on multiple Git repositories and may need to check the commit logs of several repositories at the same time. The `glog` subcommand comes in handy for such scenarios.
+It allows you to view the commit logs of all Git repositories in a given directory. Developers often work on multiple Git repositories and may need to check the commit logs of several repositories at the same time. The `glog` subcommand comes in handy for such scenarios.
- usage:
+usage:
```
lwe glog [git repo dir] [-a=yesAnd] [-n=50] [-s=2023-08-04] [-e=2023-08-04]
```
#### gl: Enhances the code pulling feature
- Pulls the latest code from all Git repositories in a given directory (using `git pull --rebase`).
+Pulls the latest code from all Git repositories in a given directory (using `git pull --rebase`).
- usage:
+usage:
```
lwe gl [git repo dir]
```
#### gcl: Enhances the `git clone` feature
- usage:
+usage:
```
lwe gcl gitGroupUrl [dir for this git group] -t=yourToken
```
#### gst: Views the status of all Git repositories in a specified directory
- usage:
+usage:
```
lwe gst [your git repo dir]
```
@@ -73,7 +75,8 @@ usage:
lwe fmt sql-file-path [-t=java|go|json] [-a=yesAnd]
```
-For detailed usage instructions, please refer to the Wiki.
+For detailed usage instructions, please refer to the [Wiki](https://github.com/yesAnd92/lwe/wiki/1.%E5%BB%BA%E8%A1%A8SQL%E8%AF%AD%E5%8F%A5%E7%94%9F%E6%88%90%E4%B8%8D%E7%94%A8%E8%AF%AD%E8%A8%80%E6%89%80%E9%9C%80%E5%AE%9E%E4%BD%93)
+
SQL Statement Generation of DSL Statements
`lwe es [optional parameters] `
@@ -85,51 +88,58 @@ Supported SQL operations in the current version:
lwe es 'select * from user where age >18' [-p=true]
```
-For detailed usage instructions, please refer to the Wiki.
+For detailed usage instructions, please refer to the [Wiki](https://github.com/yesAnd92/lwe/wiki/2.%E5%B0%86SQL%E8%AF%AD%E5%8F%A5%E8%BD%AC%E6%8D%A2%E6%88%90ElasticSearch%E6%9F%A5%E8%AF%A2%E7%9A%84DSL%E8%AF%AD%E8%A8%80)
PDF Tools: Merging Multiple Images or PDFs, Extracting Specific Pages from PDFs
Simple editing of PDFs is a rather common feature, such as merging several PDFs or images into one, or extracting specific pages from a PDF. While this is a paid feature in many office software, LWE provides the capability for simple PDF editing.
#### pdfm: Merge PDFs or images
- Combines multiple PDF or image files into a single PDF file in a specified order.
- usage:
+Combines multiple PDF or image files into a single PDF file in a specified order.
+usage:
```
lwe pdfm out.pdf in1.pdf,in2.jpg,*.png,in3.pdf ...
```
#### pdfc: Extract specified pages from a PDF
- Extracts corresponding pages from a PDF and generates a PDF file based on specified page numbers.
- usage:
+Extracts corresponding pages from a PDF and generates a PDF file based on specified page numbers.
+usage:
```
lwe pdfc [-m] in.pdf outDir 2,3,5,7-9,15 ...
```
-For detailed usage instructions, please refer to the Wiki.
+For detailed usage instructions, please refer to the [Wiki](https://github.com/yesAnd92/lwe/wiki/PDF%E5%B7%A5%E5%85%B7%EF%BC%9A%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AA%E5%9B%BE%E7%89%87%E6%88%96%E8%80%85PDF%E3%80%81%E6%88%AA%E5%8F%96PDF%E6%8C%87%E5%AE%9A%E9%A1%B5#pdfm-%E5%90%88%E5%B9%B6pdf%E6%88%96%E8%80%85%E5%9B%BE%E7%89%87)
+
+Other utilities
+Some highly practical and efficient tools
-Other Small Tools
-Some very practical features:
Formatting request URLs
Sometimes the URL for a request can be very long, making it difficult to find the target parameters. The `url` command can be used to format the URL, increasing the readability of the request.
- usage:
+
+usage:
```
lwe url yourUrl
```
+For detailed, [Wiki](https://github.com/yesAnd92/lwe/wiki/%E5%85%B6%E5%AE%83%E5%B0%8F%E5%B7%A5%E5%85%B7#%E6%A0%BC%E5%BC%8F%E5%8C%96%E8%AF%B7%E6%B1%82url)
+
Retrieving passwords from Navicat connection configurations
If you want to retrieve the username/password for a corresponding database from a connection saved in Navicat, you can use the `ncx` file. The `ncx` file is a connection configuration file exported by Navicat, but the password in the `ncx` file is an encrypted hexadecimal string. The `ncx` command can retrieve the corresponding plaintext.
- usage:
+
+usage:
```
lwe ncx ncx-file-path
```
+For detailed, [Wiki](https://github.com/yesAnd92/lwe/wiki/%E5%85%B6%E5%AE%83%E5%B0%8F%E5%B7%A5%E5%85%B7#%E8%8E%B7%E5%8F%96navicat%E8%BF%9E%E6%8E%A5%E9%85%8D%E7%BD%AE%E4%B8%AD%E7%9A%84%E5%AF%86%E7%A0%81)
Synchronizing files between two directories
If you have a habit of backing up files, this tool might help you. It can synchronize newly added files from the source directory to the backup directory, saving you the trouble of manually syncing each folder and file one by one.
- usage:
+
+usage:
```
lwe fsync sourceDir targetDir [-d=true]
```
+For detailed, [Wiki](https://github.com/yesAnd92/lwe/wiki/%E5%85%B6%E5%AE%83%E5%B0%8F%E5%B7%A5%E5%85%B7#%E5%90%8C%E6%AD%A5%E4%B8%A4%E4%B8%AA%E7%9B%AE%E5%BD%95%E4%B8%8B%E6%96%87%E4%BB%B6)
-For detailed usage instructions, please refer to the Wiki.
## Disclaimer
1. The spf13/cobra library is used to conveniently build command-line tools.
@@ -143,5 +153,5 @@ For detailed usage instructions, please refer to the Wiki.
- `es`: Add support for insert, update, delete operations as required.
- ...
-## Open Source License
+## License
MIT License
diff --git a/README.md b/README.md
index d7ef4b3..677056d 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-**[中文文档](README.zh-CN.md)**
+**[English](README.EN.md)**
## lwe
lwe是leave work early的缩写,也就是"早点下班"!🤣🤣🤣
它是一个帮助开发者提高工作效率的跨平台命令行工具,当然你把它当做go入门学习的项目也是合适的!
diff --git a/README.zh-CN.md b/README.zh-CN.md
deleted file mode 100644
index d6c1d19..0000000
--- a/README.zh-CN.md
+++ /dev/null
@@ -1,193 +0,0 @@
-## lwe
-lwe是leave work early的缩写,也就是"早点下班"!🤣🤣🤣
-它是一个帮助开发者提高工作效率的跨平台命令行工具,当然你把它当做go入门学习的项目也是合适的!
-总之,欢迎提issue、提好玩或者使用的功能需求,最好能直接PR参与到项目中,大家一起努力,争取早点下班!!! 💪💪💪
-
-
-## 功能
-
-[Git增强多仓库操作能力:glog、gl、gcl、gst](#git)
-
-[由建表SQL语句转换成Java Bean、Go结构体、Json等](#fmt)
-
-[将SQL语句转换成ElasticSearch查询的DSL语言](#es)
-
-[PDF工具:合并多个图片或者PDF、截取PDF指定页](#pdf)
-
-[其它小工具](#other)
-- 获取Navicat连接配置中的密码
-- 同步两个目录下文件
-- 格式化请求url
-
-
-## 安装
-### 下载编译后的可执行文件
-
-到[release](https://github.com/yesAnd92/lwe/releases)页获取对应平台的版本,在终端上即可使用该二进制文件!
-
-当然,更推荐的方式是将二进制文件配置到环境变量中,这样可以随时随地使用二进制文件
-
-更多的安装方式和注意事项,查查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/0.%E5%AE%89%E8%A3%85%E3%80%81%E9%85%8D%E7%BD%AE%E4%BD%BF%E7%94%A8)
-
-
-
-## 使用
-
-你可以输入`lwe` 查看lwe命令的使用方式,有哪些子命令及其各自对的功能描述。
-
-如果对某个子命令感兴趣,可以使用`-h`参数查看命令的使用示例 ,如:`lwe glog -h`
-
-
-Git增强多仓库操作能力:glog、gl、gcl、gst
-这里是几个围绕git相关的增强命令,基本都是在原语义上增加了一些跨git仓库的操作
-
-Git增强功能详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/3.Git%E5%A2%9E%E5%BC%BA%E5%8A%9F%E8%83%BD)
-
-#### glog 增强Git日志功能
-查看给定目录下所有git仓库提交日志
-开发人员通常会在多个git仓库下工作,经常会有同时查看多个git仓库提交日志的需求,glog子命令就派上用场了。
-
-使用方式:
-
-```text
-lwe glog [git repo dir] [-a=yesAnd] [-n=50] [-s=2023-08-04] [-e=2023-08-04]
-```
-
-
-#### gl 增强拉取代码功能
-拉取给定目录下的所有git仓库最新代码(使用的git pull --rebase的方式)
-
-
-
-使用方式:
-```text
-lwe gl [git repo dir]
-```
-
-#### gcl 增强git clone功能
-使用方式:
-```text
-lwe gcl gitGroupUrl [dir for this git group] -t=yourToken
-```
-
-#### gst 查看指定目录下所有git仓库状态
-查看给定目录下的所有git仓库状态
-
-使用方式:
-```text
-lwe gst [your git repo dir]
-```
-***
-
-建表语句生成Java Bean实体、Go 结构体等
-
-如果我们已经有了表结构,使用建表语句生成对应的实体可以大大减少我们"无脑且重复"工作。
-目前支持生成的结构包括Java、Go、Json。
-
-使用方式:
-
-```text
-lwe fmt sql-file-path [-t=java|go|json] [-a=yesAnd]
-```
-详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/1.%E5%BB%BA%E8%A1%A8SQL%E8%AF%AD%E5%8F%A5%E7%94%9F%E6%88%90%E4%B8%8D%E7%94%A8%E8%AF%AD%E8%A8%80%E6%89%80%E9%9C%80%E5%AE%9E%E4%BD%93)
-
-***
-
-SQL语句生成DSL语句
-
-```bash
-lwe es [可选参数]
-```
-
-这个命令可以帮我们从繁琐的ES查询语法中解脱出来,它可以将sql语句转换成响应的DSL,并且以curl命令的形式输出,这样服务器上也可以方便的使用。
-当前版本支持的SQL操作
-
-使用方式:
-
-```text
-lwe es 'select * from user where age >18' [-p=true]
-```
-详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/2.%E5%B0%86SQL%E8%AF%AD%E5%8F%A5%E8%BD%AC%E6%8D%A2%E6%88%90ElasticSearch%E6%9F%A5%E8%AF%A2%E7%9A%84DSL%E8%AF%AD%E8%A8%80)
-
-***
-
-PDF工具:合并多个图片或者PDF、截取PDF指定页
-
-对PDF进行简单的编辑还是挺常用的功能,比如把几个PDF、图片合并成一个PDF,从一个PDF中抽离出指定页等,但是在很多办公软件上收费的功能,lwe提供了简单编辑PDF的能力。
-
-#### pdfm 合并PDF或者图片
-按照指定的文件顺序,将多个PDF、图片文件合并成一个PDF文件
-
-使用方式:
-```text
-lwe pdfm out.pdf in1.pdf,in2.jpg,*.png,in3.pdf ...
-```
-详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/PDF%E5%B7%A5%E5%85%B7%EF%BC%9A%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AA%E5%9B%BE%E7%89%87%E6%88%96%E8%80%85PDF%E3%80%81%E6%88%AA%E5%8F%96PDF%E6%8C%87%E5%AE%9A%E9%A1%B5#pdfm-%E5%90%88%E5%B9%B6pdf%E6%88%96%E8%80%85%E5%9B%BE%E7%89%87)
-
-
-#### pdfc 从PDF中截取指定的页
-按照指定的页码,从PDF中截取对应的页生成PDF文件
-
-使用方式:
-```text
-lwe pdfc [-m] in.pdf outDir 2,3,5,7-9,15 ...
-```
-详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/PDF%E5%B7%A5%E5%85%B7%EF%BC%9A%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AA%E5%9B%BE%E7%89%87%E6%88%96%E8%80%85PDF%E3%80%81%E6%88%AA%E5%8F%96PDF%E6%8C%87%E5%AE%9A%E9%A1%B5#pdfc-%E4%BB%8Epdf%E4%B8%AD%E6%88%AA%E5%8F%96%E6%8C%87%E5%AE%9A%E7%9A%84%E9%A1%B5)
-
-***
-
-其它小工具
-一些非常实用的功能
-
-格式化请求url
-有时请求的url很长,不利于我们找到目标参数,可以使用url命令进行格式化,增加请求的可读性
-
-使用方式:
-
-```text
-lwe url yourUrl
-```
-详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/%E5%85%B6%E5%AE%83%E5%B0%8F%E5%B7%A5%E5%85%B7#%E6%A0%BC%E5%BC%8F%E5%8C%96%E8%AF%B7%E6%B1%82url)
-
-
-获取Navicat连接配置中的密码
-如果想从Navicat保存的连接中获取对应数据库的用户名/密码,可以使用ncx文件,ncx文件是Navicat导出的连接配置文件,但ncx中的密码是一个加密后的十六进制串,使用ncx命令可以获取对应的明文
-
-使用方式:
-
-```text
-lwe ncx ncx-file-path
-```
-详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/%E5%85%B6%E5%AE%83%E5%B0%8F%E5%B7%A5%E5%85%B7#%E8%8E%B7%E5%8F%96navicat%E8%BF%9E%E6%8E%A5%E9%85%8D%E7%BD%AE%E4%B8%AD%E7%9A%84%E5%AF%86%E7%A0%81)
-
-同步两个目录下文件
-如果你有备份文件的习惯,这个工具可能会帮到你,它可以将源目录文件下的新增的文件同步到备份目录,省去了你逐层文件夹逐个文件去手动同步。
-
-使用方式:
-```text
-lwe fsync sourceDir targetDir [-d=true]
-```
-
-详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/%E5%85%B6%E5%AE%83%E5%B0%8F%E5%B7%A5%E5%85%B7#%E5%90%8C%E6%AD%A5%E4%B8%A4%E4%B8%AA%E7%9B%AE%E5%BD%95%E4%B8%8B%E6%96%87%E4%BB%B6)
-
-
-
-## 声明
-1.使用[spf13/cobra](github.com/spf13/cobra)库来方便的构建命令行工具
-
-2.es子命令实现借助了[sqlparser](github.com/xwb1989/sqlparser)库来解析SQL语句,一个库很优秀的解析SQL库
-
-3.sql转换成dsl,曹大的[elasticsql](https://github.com/cch123/elasticsql)项目已经是一个很成熟好用的轮子了,lwe也大量借鉴了它的实现思路;没直接调用这个库的原因是想自己练手,同时后续增减功能也更加灵活
-
-4.git增强命令结果输出时使用了[go-pretty](https://github.com/jedib0t/go-pretty)库来表格化提交信息
-
-5.pdf命令是在[pdfcpu](https://github.com/pdfcpu/pdfcpu)基础上进行的封装
-
-## RoadMap
-- fmt 根据需求支持更多类型的转换
-- es 按需增加对insert、update、delete
- ......
-
-## 开源协议
-
-[MIT License](https://github.com/yesAnd92/lwe/blob/main/LICENSE)
From 6c58c75dbdeb9272618de53e165de72963f251c7 Mon Sep 17 00:00:00 2001
From: yesAnd <850208971@qq.com>
Date: Wed, 10 Jul 2024 15:27:27 +0800
Subject: [PATCH 5/6] update en readme.md
---
README.EN.md | 1 +
README.md | 10 ++++++++++
handler/env/env_variable_test.go | 3 ++-
3 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/README.EN.md b/README.EN.md
index a27d284..2b44e87 100644
--- a/README.EN.md
+++ b/README.EN.md
@@ -19,6 +19,7 @@ In short, feel free to submit issues, fun features, or usage feedback. It would
[Other utilities](#other)
- Retrieving passwords from Navicat connection configurations
- Synchronizing files between two directories
+- Show the environmental variables you configured
- Formatting request URLs
## Installation
diff --git a/README.md b/README.md
index 677056d..21261ee 100644
--- a/README.md
+++ b/README.md
@@ -18,6 +18,7 @@ lwe是leave work early的缩写,也就是"早点下班"!🤣🤣🤣
[其它小工具](#other)
- 获取Navicat连接配置中的密码
- 同步两个目录下文件
+- 显示本机配置的环境变量
- 格式化请求url
@@ -172,6 +173,15 @@ lwe fsync sourceDir targetDir [-d=true]
详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/%E5%85%B6%E5%AE%83%E5%B0%8F%E5%B7%A5%E5%85%B7#%E5%90%8C%E6%AD%A5%E4%B8%A4%E4%B8%AA%E7%9B%AE%E5%BD%95%E4%B8%8B%E6%96%87%E4%BB%B6)
+显示环境变量
+显示本机配置的环境变量,目前仅测试了mac平台
+
+使用方式:
+
+```text
+lwe env
+```
+
## 声明
1.使用[spf13/cobra](github.com/spf13/cobra)库来方便的构建命令行工具
diff --git a/handler/env/env_variable_test.go b/handler/env/env_variable_test.go
index f40399c..f48cc01 100644
--- a/handler/env/env_variable_test.go
+++ b/handler/env/env_variable_test.go
@@ -6,5 +6,6 @@ import (
func TestMacEVnVariable_findEnvInfo(t *testing.T) {
mac := &MacEVnVariable{}
- mac.FindEnvInfo()
+
+ EnvCat(mac.FindEnvInfo())
}
From 9e4f7a5f4cded2c8b37e384a2a090a61dc6602c8 Mon Sep 17 00:00:00 2001
From: yesAnd <850208971@qq.com>
Date: Wed, 10 Jul 2024 17:35:11 +0800
Subject: [PATCH 6/6] remove pdf command
---
README.EN.md | 18 ----
README.md | 27 ------
cmd/pdf.go | 93 -------------------
cmd/root.go | 2 -
go.mod | 8 +-
go.sum | 44 ---------
handler/pdf/pdf_cut.go | 106 ---------------------
handler/pdf/pdf_cut_test.go | 93 -------------------
handler/pdf/pdf_merge.go | 124 -------------------------
handler/pdf/pdf_merge_test.go | 97 -------------------
handler/pdf/pdfcpu_api_test.go | 94 -------------------
handler/pdf/testdata/Paclitaxel.PDF | Bin 30519 -> 0 bytes
handler/pdf/testdata/blank-scan.pdf | Bin 5447 -> 0 bytes
handler/pdf/testdata/bookletTest.pdf | Bin 50308 -> 0 bytes
handler/pdf/testdata/empty.pdf | Bin 811 -> 0 bytes
handler/pdf/testdata/github.png | Bin 1714 -> 0 bytes
handler/pdf/testdata/logoSmall.png | Bin 294497 -> 0 bytes
handler/pdf/testdata/logoVerySmall.png | Bin 88641 -> 0 bytes
handler/pdf/testdata/lwe.jpg | Bin 16155 -> 0 bytes
handler/pdf/testdata/mountain.jpx | Bin 887463 -> 0 bytes
handler/pdf/testdata/testRot.pdf | Bin 1189 -> 0 bytes
handler/pdf/testdata/zineTest.pdf | Bin 6887 -> 0 bytes
22 files changed, 1 insertion(+), 705 deletions(-)
delete mode 100644 cmd/pdf.go
delete mode 100644 handler/pdf/pdf_cut.go
delete mode 100644 handler/pdf/pdf_cut_test.go
delete mode 100644 handler/pdf/pdf_merge.go
delete mode 100644 handler/pdf/pdf_merge_test.go
delete mode 100644 handler/pdf/pdfcpu_api_test.go
delete mode 100644 handler/pdf/testdata/Paclitaxel.PDF
delete mode 100644 handler/pdf/testdata/blank-scan.pdf
delete mode 100644 handler/pdf/testdata/bookletTest.pdf
delete mode 100644 handler/pdf/testdata/empty.pdf
delete mode 100644 handler/pdf/testdata/github.png
delete mode 100644 handler/pdf/testdata/logoSmall.png
delete mode 100644 handler/pdf/testdata/logoVerySmall.png
delete mode 100644 handler/pdf/testdata/lwe.jpg
delete mode 100644 handler/pdf/testdata/mountain.jpx
delete mode 100644 handler/pdf/testdata/testRot.pdf
delete mode 100644 handler/pdf/testdata/zineTest.pdf
diff --git a/README.EN.md b/README.EN.md
index 2b44e87..cc8d442 100644
--- a/README.EN.md
+++ b/README.EN.md
@@ -91,24 +91,6 @@ lwe es 'select * from user where age >18' [-p=true]
For detailed usage instructions, please refer to the [Wiki](https://github.com/yesAnd92/lwe/wiki/2.%E5%B0%86SQL%E8%AF%AD%E5%8F%A5%E8%BD%AC%E6%8D%A2%E6%88%90ElasticSearch%E6%9F%A5%E8%AF%A2%E7%9A%84DSL%E8%AF%AD%E8%A8%80)
-PDF Tools: Merging Multiple Images or PDFs, Extracting Specific Pages from PDFs
-Simple editing of PDFs is a rather common feature, such as merging several PDFs or images into one, or extracting specific pages from a PDF. While this is a paid feature in many office software, LWE provides the capability for simple PDF editing.
-
-#### pdfm: Merge PDFs or images
-Combines multiple PDF or image files into a single PDF file in a specified order.
-usage:
- ```
- lwe pdfm out.pdf in1.pdf,in2.jpg,*.png,in3.pdf ...
- ```
-
-#### pdfc: Extract specified pages from a PDF
-Extracts corresponding pages from a PDF and generates a PDF file based on specified page numbers.
-usage:
- ```
- lwe pdfc [-m] in.pdf outDir 2,3,5,7-9,15 ...
- ```
-
-For detailed usage instructions, please refer to the [Wiki](https://github.com/yesAnd92/lwe/wiki/PDF%E5%B7%A5%E5%85%B7%EF%BC%9A%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AA%E5%9B%BE%E7%89%87%E6%88%96%E8%80%85PDF%E3%80%81%E6%88%AA%E5%8F%96PDF%E6%8C%87%E5%AE%9A%E9%A1%B5#pdfm-%E5%90%88%E5%B9%B6pdf%E6%88%96%E8%80%85%E5%9B%BE%E7%89%87)
Other utilities
Some highly practical and efficient tools
diff --git a/README.md b/README.md
index 21261ee..aae3db8 100644
--- a/README.md
+++ b/README.md
@@ -13,8 +13,6 @@ lwe是leave work early的缩写,也就是"早点下班"!🤣🤣🤣
[将SQL语句转换成ElasticSearch查询的DSL语言](#es)
-[PDF工具:合并多个图片或者PDF、截取PDF指定页](#pdf)
-
[其它小工具](#other)
- 获取Navicat连接配置中的密码
- 同步两个目录下文件
@@ -113,31 +111,6 @@ lwe es 'select * from user where age >18' [-p=true]
***
-PDF工具:合并多个图片或者PDF、截取PDF指定页
-
-对PDF进行简单的编辑还是挺常用的功能,比如把几个PDF、图片合并成一个PDF,从一个PDF中抽离出指定页等,但是在很多办公软件上收费的功能,lwe提供了简单编辑PDF的能力。
-
-#### pdfm 合并PDF或者图片
-按照指定的文件顺序,将多个PDF、图片文件合并成一个PDF文件
-
-使用方式:
-```text
-lwe pdfm out.pdf in1.pdf,in2.jpg,*.png,in3.pdf ...
-```
-详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/PDF%E5%B7%A5%E5%85%B7%EF%BC%9A%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AA%E5%9B%BE%E7%89%87%E6%88%96%E8%80%85PDF%E3%80%81%E6%88%AA%E5%8F%96PDF%E6%8C%87%E5%AE%9A%E9%A1%B5#pdfm-%E5%90%88%E5%B9%B6pdf%E6%88%96%E8%80%85%E5%9B%BE%E7%89%87)
-
-
-#### pdfc 从PDF中截取指定的页
-按照指定的页码,从PDF中截取对应的页生成PDF文件
-
-使用方式:
-```text
-lwe pdfc [-m] in.pdf outDir 2,3,5,7-9,15 ...
-```
-详细使用说明,可以查阅[Wiki](https://github.com/yesAnd92/lwe/wiki/PDF%E5%B7%A5%E5%85%B7%EF%BC%9A%E5%90%88%E5%B9%B6%E5%A4%9A%E4%B8%AA%E5%9B%BE%E7%89%87%E6%88%96%E8%80%85PDF%E3%80%81%E6%88%AA%E5%8F%96PDF%E6%8C%87%E5%AE%9A%E9%A1%B5#pdfc-%E4%BB%8Epdf%E4%B8%AD%E6%88%AA%E5%8F%96%E6%8C%87%E5%AE%9A%E7%9A%84%E9%A1%B5)
-
-***
-
其它小工具
一些非常实用的功能
diff --git a/cmd/pdf.go b/cmd/pdf.go
deleted file mode 100644
index 9822a5b..0000000
--- a/cmd/pdf.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package cmd
-
-import (
- "github.com/spf13/cobra"
- "github.com/yesAnd92/lwe/handler/pdf"
- "os"
- "strings"
-)
-
-/**
-* pdf命令相关功能
- */
-var (
- merge bool = false
-
- pdfMergeCmd = &cobra.Command{
- Use: `pdfm`,
- Short: `Merge PDF or images into one PDF file`,
- Long: `Merge multiple PDF or images(png|jpg|jpeg) into one PDF file in a gaven `,
- Example: `lwe pdfm out.pdf in1.pdf,in2.jpg,*.png,in3.pdf ...`,
- Args: cobra.MatchAll(),
- Run: func(cmd *cobra.Command, args []string) {
-
- if len(args) != 2 {
- cobra.CheckErr("Please re-check syntax and try it again!")
- }
-
- outPdf := strings.TrimSpace(args[0])
- if len(outPdf) == 0 || !pdf.HasPdfExtension(outPdf) {
- cobra.CheckErr("Please ensure the output is a file with .pdf suffix!")
- }
-
- var infiles []string
-
- infiles, err := pdf.ParseMergeArg(args[1])
- if err != nil {
- cobra.CheckErr("Please ensure the input file is correct!")
- }
-
- if err, f := pdf.CheckCorrectFileExtension(infiles); !f {
- cobra.CheckErr(err)
- }
-
- mergeErr := pdf.HandlePdfMerge(outPdf, infiles)
- if mergeErr != nil {
- defer func() {
- //remove out.pdf when error occurs
- os.Remove(outPdf)
- }()
- cobra.CheckErr(mergeErr)
- }
-
- },
- }
-
- pdfCutCmd = &cobra.Command{
- Use: `pdfc`,
- Short: `Extract selected pages from pdf files`,
- Long: `Extract selected pages from PDF files into single page PDFs,or merge PDFs into one page PDF`,
- Example: `lwe pdfc [-m] in.pdf outDir 2,3,5,7-9,15 ...`,
- Args: cobra.MatchAll(),
- Run: func(cmd *cobra.Command, args []string) {
-
- if len(args) != 3 {
- cobra.CheckErr("Please re-check syntax and try it again!")
- }
-
- inPdf := args[0]
- if len(inPdf) == 0 || !pdf.HasPdfExtension(inPdf) {
- cobra.CheckErr("Please ensure the input is a file with .pdf suffix!")
- }
-
- outDir := args[1]
-
- selectedPages, err := pdf.ParseCutArg(args[2])
- if err != nil {
- cobra.CheckErr("Please ensure the page Nums you input is correct!")
- }
-
- mergeErr := pdf.HandlePdfCut(inPdf, outDir, selectedPages, merge)
- if mergeErr != nil {
- cobra.CheckErr(mergeErr)
- }
-
- },
- }
-)
-
-func init() {
-
- pdfCutCmd.PersistentFlags().BoolVarP(&merge, "merge", "m", false, "merge all selected pages into one PDF,default is false")
-
-}
diff --git a/cmd/root.go b/cmd/root.go
index 805cb98..c6e8053 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -48,8 +48,6 @@ func init() {
rootCmd.AddCommand(gclCmd)
rootCmd.AddCommand(gstCmd)
rootCmd.AddCommand(fsyncCmd)
- rootCmd.AddCommand(pdfMergeCmd)
- rootCmd.AddCommand(pdfCutCmd)
rootCmd.AddCommand(envCmd)
}
diff --git a/go.mod b/go.mod
index b2db9c1..8c5a260 100644
--- a/go.mod
+++ b/go.mod
@@ -5,24 +5,18 @@ go 1.18
require (
github.com/jedib0t/go-pretty/v6 v6.4.6
github.com/micro-plat/lib4go v1.2.0
- github.com/pdfcpu/pdfcpu v0.5.0
+ github.com/pkg/errors v0.9.1
github.com/spf13/cobra v1.6.1
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2
)
require (
github.com/clbanning/mxj v1.8.4 // indirect
- github.com/hhrutter/lzw v1.0.0 // indirect
- github.com/hhrutter/tiff v1.0.1 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
- github.com/kr/text v0.2.0 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
- github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
- golang.org/x/image v0.11.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.12.0 // indirect
- gopkg.in/yaml.v2 v2.4.0 // indirect
)
diff --git a/go.sum b/go.sum
index 382f555..d627f49 100644
--- a/go.sum
+++ b/go.sum
@@ -1,29 +1,19 @@
github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/hhrutter/lzw v1.0.0 h1:laL89Llp86W3rRs83LvKbwYRx6INE8gDn0XNb1oXtm0=
-github.com/hhrutter/lzw v1.0.0/go.mod h1:2HC6DJSn/n6iAZfgM3Pg+cP1KxeWc3ezG8bBqW5+WEo=
-github.com/hhrutter/tiff v1.0.1 h1:MIus8caHU5U6823gx7C6jrfoEvfSTGtEFRiM8/LOzC0=
-github.com/hhrutter/tiff v1.0.1/go.mod h1:zU/dNgDm0cMIa8y8YwcYBeuEEveI4B0owqHyiPpJPHc=
github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jedib0t/go-pretty/v6 v6.4.6 h1:v6aG9h6Uby3IusSSEjHaZNXpHFhzqMmjXcPq1Rjl9Jw=
github.com/jedib0t/go-pretty/v6 v6.4.6/go.mod h1:Ndk3ase2CkQbXLLNf5QDHoYb6J9WtVfmHZu9n8rk2xs=
-github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
-github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/micro-plat/lib4go v1.2.0 h1:cho4rFfWdwVWefIbFPP7cXghIlKLN0H8k3PX6QdqN0c=
github.com/micro-plat/lib4go v1.2.0/go.mod h1:yh2gi/oGoebmVKH6zUJo0V8BmE7Ogx2biuVTRn1R9zk=
-github.com/pdfcpu/pdfcpu v0.5.0 h1:F3wC4bwPbaJM+RPgm1D0Q4SAUwxElw7BhwNvL3iPgDo=
-github.com/pdfcpu/pdfcpu v0.5.0/go.mod h1:UPcHdWcMw1V6Bo5tcWHd3jZfkG8cwUwrJkQOlB6o+7g=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
@@ -46,46 +36,12 @@ github.com/stretchr/testify v1.7.4 h1:wZRexSlwd7ZXfKINDLsO4r7WBt3gTKONc6K/VesHvH
github.com/stretchr/testify v1.7.4/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 h1:zzrxE1FKn5ryBNl9eKOeqQ58Y/Qpo3Q9QNxKHX5uzzQ=
github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2/go.mod h1:hzfGeIUDq/j97IG+FhNqkowIyEcD88LrW6fyU3K3WqY=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
-golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/handler/pdf/pdf_cut.go b/handler/pdf/pdf_cut.go
deleted file mode 100644
index 4cd0f2a..0000000
--- a/handler/pdf/pdf_cut.go
+++ /dev/null
@@ -1,106 +0,0 @@
-package pdf
-
-import (
- "errors"
- "fmt"
- "github.com/pdfcpu/pdfcpu/pkg/api"
- "github.com/yesAnd92/lwe/utils"
- "os"
- "path/filepath"
- "strconv"
- "strings"
-)
-
-var ERROR_NOT_NUMBER = "the two sides of the '-' symbol are not numbers!"
-
-func ParseCutArg(args string) ([]string, error) {
-
- var pages []string
-
- //multiple page are separated by ","
- argArr := strings.Split(strings.ReplaceAll(args, " ", ""), ",")
-
- for _, arg := range argArr {
- if len(arg) == 0 {
- continue
- }
- //parse range pages by "-"
- if strings.Contains(arg, "-") {
- var l, r int
- var el, er error
- s := strings.Split(arg, "-")
- l, el = strconv.Atoi(s[0])
- r, er = strconv.Atoi(s[1])
- if el != nil || er != nil {
- return nil, errors.New(ERROR_NOT_NUMBER)
- }
- pages = append(pages, populateSuccessivePages(l, r)...)
- continue
- }
-
- if !isNumeric(arg) {
- return nil, errors.New(ERROR_NOT_NUMBER)
- }
- pages = append(pages, arg)
-
- }
-
- return pages, nil
-}
-
-func HandlePdfCut(inPdf, outDir string, selectedPages []string, merge bool) error {
-
- utils.MkdirIfNotExist(outDir)
-
- err := api.ExtractPagesFile(inPdf, outDir, selectedPages, nil)
- if err != nil {
- return err
- }
-
- if merge {
-
- originName := strings.TrimSuffix(filepath.Base(inPdf), ".pdf")
-
- //find all generated pdf by rule('{originName}_page_*.pdf')
- //but it may contain the pdf which has existed under dir before
- matches, matchErr := filepath.Glob(filepath.Join(outDir, fmt.Sprintf("%s_page_*.pdf", originName)))
- if matchErr != nil {
- return matchErr
- }
-
- defer func() {
- for _, p := range matches {
- os.Remove(p)
- }
- }()
-
- outMergeFile := filepath.Join(outDir, fmt.Sprintf("%s_selected.pdf", originName))
-
- //merge single pdf but this ignores the order that user input
- mergeErr := HandlePdfMerge(outMergeFile, matches)
- if mergeErr != nil {
- return err
- }
- }
-
- fmt.Println("PDF cut result >> " + utils.ToAbsPath(outDir))
-
- return nil
-}
-
-func populateSuccessivePages(l int, r int) (pages []string) {
-
- for i := l; i <= r; i++ {
- pages = append(pages, strconv.Itoa(i))
- }
- return
-}
-
-func isNumeric(s string) bool {
- for _, c := range s {
- if c < '0' || c > '9' {
- return false
- }
- }
- return true
-}
diff --git a/handler/pdf/pdf_cut_test.go b/handler/pdf/pdf_cut_test.go
deleted file mode 100644
index 2593ff1..0000000
--- a/handler/pdf/pdf_cut_test.go
+++ /dev/null
@@ -1,93 +0,0 @@
-package pdf
-
-import (
- "reflect"
- "testing"
-)
-
-func TestParseCutArg(t *testing.T) {
-
- tests := []struct {
- name string
- args string
- want []string
- wantErr bool
- }{
- // TODO: Add test cases.
- {
- name: "case 1",
- args: "1, 2, 4-9,20",
- want: []string{"1", "2", "4", "5", "6", "7", "8", "9", "20"},
- wantErr: false,
- },
-
- {
- name: "case 2",
- args: "1, 2, a-9,20",
- want: nil,
- wantErr: true,
- },
-
- {
- name: "case 3",
- args: "1, ,,,,",
- want: []string{"1"},
- wantErr: false,
- },
- }
-
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := ParseCutArg(tt.args)
- if (err != nil) != tt.wantErr {
- t.Errorf("ParseCutArg() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("ParseCutArg() got = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestHandlePdfCut(t *testing.T) {
- type args struct {
- inPdf string
- outDir string
- selectedPages []string
- merger bool
- }
- tests := []struct {
- name string
- args args
- wantErr bool
- }{
- // TODO: Add test cases.
- {
- name: "case 1",
- args: args{
- inPdf: "testdata/zineTest.pdf",
- outDir: "testdata/out/",
- selectedPages: []string{"1", "3", "4", "6", "20"},
- },
- wantErr: false,
- },
- {
- name: "merge all pdf",
- args: args{
- inPdf: "testdata/zineTest.pdf",
- outDir: "testdata/out/",
- selectedPages: []string{"1", "3", "5"},
- merger: true,
- },
- wantErr: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- if err := HandlePdfCut(tt.args.inPdf, tt.args.outDir, tt.args.selectedPages, tt.args.merger); (err != nil) != tt.wantErr {
- t.Errorf("HandlePdfCut() error = %v, wantErr %v", err, tt.wantErr)
- }
- })
- }
-}
diff --git a/handler/pdf/pdf_merge.go b/handler/pdf/pdf_merge.go
deleted file mode 100644
index 3334767..0000000
--- a/handler/pdf/pdf_merge.go
+++ /dev/null
@@ -1,124 +0,0 @@
-package pdf
-
-import (
- "errors"
- "fmt"
- "github.com/pdfcpu/pdfcpu/pkg/api"
- "github.com/pdfcpu/pdfcpu/pkg/pdfcpu"
- "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types"
- "github.com/yesAnd92/lwe/utils"
- "path/filepath"
- "strings"
-)
-
-var DEFALUT_IMPORT_CONFIG *pdfcpu.Import
-
-func init() {
- DEFALUT_IMPORT_CONFIG = &pdfcpu.Import{
- PageDim: types.PaperSize["A4"],
- PageSize: "A4",
- Pos: types.Full,
- Scale: 0.5,
- InpUnit: types.POINTS,
- }
-}
-
-func HandlePdfMerge(outPdf string, filenames []string) error {
-
- size := len(filenames)
- for i := 0; i < size; {
- file := filenames[i]
- var tmpImgFiles []string
-
- //same type file merge in one operation
- if HasImgExtension(file) {
- tmpImgFiles = append(tmpImgFiles, file)
- for j := i + 1; j < size; j++ {
- if HasImgExtension(filenames[j]) {
- tmpImgFiles = append(tmpImgFiles, filenames[j])
-
- continue
- }
- break
- }
- i += len(tmpImgFiles)
-
- err := api.ImportImagesFile(tmpImgFiles, outPdf, DEFALUT_IMPORT_CONFIG, nil)
- if err != nil {
- return err
- }
- }
-
- var tmpPdfFiles []string
- if HasPdfExtension(file) {
- tmpPdfFiles = append(tmpPdfFiles, file)
- for j := i + 1; j < size; j++ {
- if HasPdfExtension(filenames[j]) {
- tmpPdfFiles = append(tmpPdfFiles, filenames[j])
-
- continue
- }
- break
- }
- i += len(tmpPdfFiles)
-
- if err := api.MergeAppendFile(tmpPdfFiles, outPdf, nil); err != nil {
- return err
- }
- }
- fmt.Println("PDF merge result >> " + utils.ToAbsPath(outPdf))
- }
- return nil
-}
-
-func ParseMergeArg(arg string) ([]string, error) {
-
- var mergeParams []string
-
- //multiple PDF file are separated by ","
- argArr := strings.Split(arg, ",")
- for i := 0; i < len(argArr); i++ {
- in := strings.TrimSpace(argArr[i])
- //support "*" match files
- if strings.Contains(in, "*") {
- matches, err := filepath.Glob(in)
- if err != nil {
- return nil, err
- }
-
- for _, match := range matches {
- mergeParams = append(mergeParams, match)
- }
-
- continue
- }
-
- mergeParams = append(mergeParams, in)
-
- }
-
- return mergeParams, nil
-}
-
-func HasPdfExtension(filename string) bool {
-
- return strings.HasSuffix(strings.ToLower(filename), ".pdf")
-}
-
-func HasImgExtension(fileName string) bool {
- ext := strings.ToLower(filepath.Ext(fileName))
- return types.MemberOf(ext, []string{".png", ".webp", ".tif", ".tiff", ".jpg", ".jpeg"})
-}
-
-func CheckCorrectFileExtension(filenames []string) (error, bool) {
-
- for _, file := range filenames {
- if HasPdfExtension(file) || HasImgExtension(file) {
- continue
- }
-
- return errors.New(fmt.Sprintf("Not support this file : %s ", file)), false
- }
-
- return nil, true
-}
diff --git a/handler/pdf/pdf_merge_test.go b/handler/pdf/pdf_merge_test.go
deleted file mode 100644
index 84b3ed0..0000000
--- a/handler/pdf/pdf_merge_test.go
+++ /dev/null
@@ -1,97 +0,0 @@
-package pdf
-
-import (
- "os"
- "reflect"
- "testing"
-)
-
-func TestParseMergeArg(t *testing.T) {
- type args struct {
- arg string
- }
- tests := []struct {
- name string
- args args
- want []string
- wantErr bool
- }{
- {
- name: "case 1",
- args: args{
- arg: "testdata/*.png",
- },
- want: []string{"testdata/github.png", "testdata/logoSmall.png", "testdata/logoVerySmall.png"},
- wantErr: false,
- },
- {
- name: "case 2",
- args: args{
- arg: "testdata/bookletTest.pdf, testdata/github.png, testdata/*.jpg",
- },
- want: []string{"testdata/bookletTest.pdf", "testdata/github.png", "testdata/lwe.jpg"},
- wantErr: false,
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := ParseMergeArg(tt.args.arg)
- if (err != nil) != tt.wantErr {
- t.Errorf("ParseMergeArg() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("ParseMergeArg() got = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestHandlePdfMerge(t *testing.T) {
- type args struct {
- outPdf string
- filenames []string
- }
- tests := []struct {
- name string
- args args
- wantErr bool
- }{
- // TODO: Add test cases.
-
- {
- name: "case 1",
- args: args{
- outPdf: "testdata/out/out.pdf",
- filenames: []string{"testdata/lwe.jpg"},
- },
- wantErr: false},
- {
- name: "case 2",
- args: args{
- outPdf: "testdata/out/out.pdf",
- filenames: []string{"testdata/lwe.jpg", "testdata/zineTest.pdf", "testdata/github.png"},
- },
- wantErr: false},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- defer func() {
- os.Remove(tt.args.outPdf)
- }()
- if err := HandlePdfMerge(tt.args.outPdf, tt.args.filenames); (err != nil) != tt.wantErr {
- t.Errorf("HandlePdfMerge() error = %v, wantErr %v", err, tt.wantErr)
- }
-
- //check out Pdf exist
- if _, err := os.Stat(tt.args.outPdf); os.IsNotExist(err) {
- t.Errorf("outPdf file does not exist")
- } else {
- data, _ := os.ReadFile(tt.args.outPdf)
- if len(data) == 0 {
- t.Errorf("outPdf file is empty")
- }
- }
- })
- }
-}
diff --git a/handler/pdf/pdfcpu_api_test.go b/handler/pdf/pdfcpu_api_test.go
deleted file mode 100644
index f30f593..0000000
--- a/handler/pdf/pdfcpu_api_test.go
+++ /dev/null
@@ -1,94 +0,0 @@
-package pdf
-
-import (
- "github.com/pdfcpu/pdfcpu/pkg/pdfcpu"
- "github.com/pdfcpu/pdfcpu/pkg/pdfcpu/types"
- "path/filepath"
- "testing"
-
- "github.com/pdfcpu/pdfcpu/pkg/api"
-)
-
-var indir = "testdata"
-var outdir = "testdata/out"
-
-func TestMergeCreateNew(t *testing.T) {
- msg := "TestMergeCreate"
- inFiles := []string{
- filepath.Join(indir, "bookletTest.pdf"),
- filepath.Join(indir, "Paclitaxel.PDF"),
- filepath.Join(indir, "blank-scan.pdf"),
- filepath.Join(indir, "bookletTest.pdf"),
- }
- outFile := filepath.Join(outdir, "out2.pdf")
-
- if err := api.MergeCreateFile(inFiles, outFile, nil); err != nil {
- t.Fatalf("%s: %v\n", msg, err)
- }
-
-}
-
-func TestValidate(t *testing.T) {
- msg := "TestValidate"
- inFiles := []string{
- filepath.Join(indir, "bookletTest.pdf"),
- filepath.Join(indir, "Paclitaxel.PDF"),
- filepath.Join(indir, "blank-scan.pdf"),
- filepath.Join(indir, "mountain.jpx"),
- }
-
- if err := api.ValidateFiles(inFiles, nil); err != nil {
- t.Fatalf("%s: %v\n", msg, err)
- }
-
-}
-
-func TestSplite(t *testing.T) {
- msg := "TestSplite"
- inFile := filepath.Join(indir, "bookletTest.pdf")
-
- if err := api.SplitFile(inFile, outdir, 2, nil); err != nil {
- t.Fatalf("%s: %v\n", msg, err)
- }
-}
-
-func TestExtractPagesFile(t *testing.T) {
-
- msg := "ExtractPagesFile"
- inFile := filepath.Join(indir, "bookletTest.pdf")
-
- // Extract a page span.
- selectedPages := []string{
- "1", "3",
- }
- err := api.ExtractPagesFile(inFile, outdir, selectedPages, nil)
- if err != nil {
- t.Fatalf("%s ExtractPages: %v\n", msg, err)
- }
-}
-
-func TestImportImagesFile(t *testing.T) {
-
- msg := "ImportImagesFile"
- inFiles := []string{
- filepath.Join(indir, "github.png"),
- filepath.Join(indir, "logoSmall.png"),
- filepath.Join(indir, "lwe.jpg"),
- }
- outPdf := filepath.Join(outdir, "out.pdf")
-
- err := api.ImportImagesFile(inFiles, outPdf, DefaultImportConfig(), nil)
- if err != nil {
- t.Fatalf("%s ExtractPages: %v\n", msg, err)
- }
-}
-
-func DefaultImportConfig() *pdfcpu.Import {
- return &pdfcpu.Import{
- PageDim: types.PaperSize["A4"],
- PageSize: "A4",
- Pos: types.Full,
- Scale: 0.5,
- InpUnit: types.POINTS,
- }
-}
diff --git a/handler/pdf/testdata/Paclitaxel.PDF b/handler/pdf/testdata/Paclitaxel.PDF
deleted file mode 100644
index d1fe5a72c380d218e6be90c47d03507951b0555f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 30519
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
diff --git a/handler/pdf/testdata/bookletTest.pdf b/handler/pdf/testdata/bookletTest.pdf
deleted file mode 100644
index a533e306f4f60e7d6287cc60ff9b374229cc67a2..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 50308
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 |