diff --git a/external_tools/tiger/codetemplate.go b/external_tools/tiger/codetemplate.go
new file mode 100644
index 0000000..b348535
--- /dev/null
+++ b/external_tools/tiger/codetemplate.go
@@ -0,0 +1,154 @@
+package main
+
+const (
+ DemoCode = `package main
+
+import (
+ "github.com/karldoenitz/Tigo/web"
+)
+
+// HelloHandler it's a demo handler
+type HelloHandler struct {
+ web.BaseHandler
+}
+
+// Get http get method
+func (h *HelloHandler) Get() {
+ // write your code here
+ h.ResponseAsHtml("Hello Tiger Go!")
+}
+
+// urls url mapping
+var urls = []web.Pattern{
+ {"/hello-world", HelloHandler{}, nil},
+}
+
+func main() {
+ application := web.Application{
+ IPAddress: "0.0.0.0",
+ Port: 8888,
+ UrlPatterns: urls,
+ }
+ application.Run()
+}
+`
+ mainCode = `package main
+
+import (
+ "github.com/karldoenitz/Tigo/web"
+ "{{ .ProjectName }}/handler"
+)
+
+// Write you url mapping here
+var urls = []web.Pattern{
+ {"/ping", handler.PingHandler{}, nil},
+}
+
+func main() {
+ application := web.Application{
+ IPAddress: "0.0.0.0",
+ Port: 8080,
+ UrlPatterns: urls,
+ }
+ application.Run()
+}
+
+`
+ handlerCode = `// you can write your code here.
+// You can add 'Post', 'Put', 'Delete' and other methods to handler.
+package handler
+
+import (
+ "github.com/karldoenitz/Tigo/web"
+)
+
+type {{ .HandlerName }} struct {
+ web.BaseHandler
+}
+
+func (p *{{ .HandlerName }}) Get() {
+ // write your code here
+ p.ResponseAsText("Pong")
+}
+
+func (p *{{ .HandlerName }}) Post() {
+ // write your code here
+ p.ResponseAsText("Pong")
+}
+
+`
+ logCode = `// you can write your code here.
+// You can modify the log level and add more logs.
+package logger
+
+import (
+ "os"
+ "github.com/sirupsen/logrus"
+)
+
+var Logger = logrus.New()
+
+func init() {
+ Logger.SetOutput(os.Stdout)
+ Logger.SetLevel(logrus.InfoLevel)
+}
+
+`
+ configCodeJson = `{
+ "cookie": "{{ .CookieKey }}",
+ "ip": "0.0.0.0",
+ "port": 8080,
+ "log": {
+ "trace": "stdout",
+ "info": "{{ .WorkDir }}/log/tigo-framework-info.log",
+ "warning": "{{ .WorkDir }}/log/tigo-framework-warning.log",
+ "error": "{{ .WorkDir }}/log/tigo-framework-info-error.log"
+ }
+}
+`
+ configCodeYaml = `cookie: {{ .CookieKey }}
+ip: 0.0.0.0
+port: 8080
+log:
+ trace: stdout
+ info: "{{ .WorkDir }}/log/tigo-framework-info.log"
+ warning: "{{ .WorkDir }}/log/tigo-framework-warning.log"
+ error: "{{ .WorkDir }}/log/tigo-framework-info-error.log"
+`
+ cmdVerbose = `
+use command tiger to create a Tigo projection.
+
+Usage:
+
+ tiger [args]
+
+The commands are:
+
+ addHandler to add a handler for Tigo projection
+ create to create a Tigo projection
+ conf to add a configuration for Tigo projection
+ logger to add a logger for Tigo projection
+ mod to run go mod
+ version to show Tigo version
+
+Use "tiger help " for more information about a command.
+
+`
+ cmdCreateVerbose = `
+use this command to create a Tigo project.
+"tiger create " can create a project with name "project_name",
+"tiger create demo" can create a demo project.
+
+`
+ cmdConfVerbose = `
+use this command to add a configuration.
+if it's an empty folder, this command will throw an error.
+the new configuration will replace the old configuration.
+
+`
+ cmdAddHandlerVerbose = `
+use this command to add a handler with defined name.
+"tiger addHandler " will add a handler named "handler_name".
+
+`
+)
diff --git a/external_tools/tiger/egg.go b/external_tools/tiger/egg.go
new file mode 100644
index 0000000..11777d3
--- /dev/null
+++ b/external_tools/tiger/egg.go
@@ -0,0 +1,221 @@
+package main
+
+import (
+ "fmt"
+ "math/rand"
+)
+
+// MapItem 定义迷宫元素枚举
+type MapItem int
+
+const (
+ MapWall MapItem = iota
+ MapGround
+ MapEntrance
+ MapExit
+ MapOutside
+ MapStep
+)
+
+// Point 定义点结构体
+type Point struct {
+ X, Y int
+}
+
+// Size 定义大小结构体
+type Size struct {
+ Width, Height int
+}
+
+// Rect 定义矩形结构体
+type Rect struct {
+ X, Y, Width, Height int
+}
+
+// Maze 迷宫结构
+type Maze struct {
+ Map [][]MapItem // 迷宫地图
+ MapSize Size // 迷宫尺寸
+ PlayerPos Point // 游戏者位置
+}
+
+// MakeMaze 生成迷宫(注:宽高必须是奇数)
+func (m *Maze) MakeMaze(width, height int) {
+ if width%2 != 1 {
+ width += 1
+ }
+
+ if height%2 != 1 {
+ height += 1
+ }
+
+ // 记录迷宫尺寸
+ m.MapSize = Size{Width: width, Height: height}
+
+ // 分配迷宫内存
+ m.Map = make([][]MapItem, width+2)
+ for x := 0; x < width+2; x++ {
+ m.Map[x] = make([]MapItem, height+2)
+ // 初始化为墙
+ for y := 0; y < height+2; y++ {
+ m.Map[x][y] = MapWall
+ }
+ }
+
+ // 定义边界
+ for x := 0; x <= width+1; x++ {
+ m.Map[x][0] = MapGround
+ m.Map[x][height+1] = MapGround
+ }
+
+ for y := 1; y <= height; y++ {
+ m.Map[0][y] = MapGround
+ m.Map[width+1][y] = MapGround
+ }
+
+ // 定义入口和出口
+ m.Map[1][2] = MapEntrance
+ m.Map[width][height-1] = MapExit
+
+ // 设置玩家初始位置
+ m.PlayerPos = Point{X: 1, Y: 2}
+
+ // 从任意点开始遍历生成迷宫
+ x := ((rand.Intn(width-1) & 0xfffe) + 2)
+ y := ((rand.Intn(height-1) & 0xfffe) + 2)
+ m.TravelMaze(x, y)
+
+ // 将边界标记为迷宫外
+ for x := 0; x <= width+1; x++ {
+ m.Map[x][0] = MapOutside
+ m.Map[x][height+1] = MapOutside
+ }
+
+ for y := 1; y <= height; y++ {
+ m.Map[0][y] = MapOutside
+ m.Map[width+1][y] = MapOutside
+ }
+}
+
+// TravelMaze 生成迷宫:遍历 (x, y) 四周
+func (m *Maze) TravelMaze(x, y int) {
+ // 定义遍历方向
+ directions := [4][2]int{{0, 1}, {1, 0}, {0, -1}, {-1, 0}}
+
+ // 将遍历方向乱序
+ for i := 0; i < 4; i++ {
+ n := rand.Intn(4)
+ directions[i], directions[n] = directions[n], directions[i]
+ }
+
+ // 尝试周围四个方向
+ m.Map[x][y] = MapGround
+ for i := 0; i < 4; i++ {
+ dx, dy := directions[i][0], directions[i][1]
+ if m.Map[x+2*dx][y+2*dy] == MapWall {
+ m.Map[x+dx][y+dy] = MapGround
+ m.TravelMaze(x+dx*2, y+dy*2) // 递归
+ }
+ }
+}
+
+// MapRoute 实现迷宫求解,使用深度优先搜索算法
+func (m *Maze) MapRoute() {
+ // 定义方向:上、右、下、左
+ directions := [4][2]int{{-1, 0}, {0, 1}, {1, 0}, {0, -1}}
+
+ // 找到入口位置
+ var start Point
+ found := false
+ for i := 0; i < m.MapSize.Width+2 && !found; i++ {
+ for j := 0; j < m.MapSize.Height+2; j++ {
+ if m.Map[i][j] == MapEntrance {
+ start = Point{X: i, Y: j}
+ found = true
+ break
+ }
+ }
+ }
+
+ if !found {
+ fmt.Println("未找到迷宫入口")
+ return
+ }
+
+ // 创建访问标记数组
+ visited := make([][]bool, m.MapSize.Width+2)
+ for i := range visited {
+ visited[i] = make([]bool, m.MapSize.Height+2)
+ }
+
+ // 记录路径的栈
+ path := []Point{start}
+ visited[start.X][start.Y] = true
+
+ // 深度优先搜索函数
+ var dfs func(x, y int) bool
+ dfs = func(x, y int) bool {
+ // 如果到达出口,返回成功
+ if m.Map[x][y] == MapExit {
+ return true
+ }
+
+ // 尝试四个方向
+ for _, dir := range directions {
+ nx, ny := x+dir[0], y+dir[1]
+
+ // 检查是否可以移动到(nx, ny)
+ if nx >= 0 && nx < m.MapSize.Width+2 &&
+ ny >= 0 && ny < m.MapSize.Height+2 &&
+ (m.Map[nx][ny] == MapGround || m.Map[nx][ny] == MapExit) &&
+ !visited[nx][ny] {
+
+ visited[nx][ny] = true
+ path = append(path, Point{X: nx, Y: ny})
+
+ // 递归搜索
+ if dfs(nx, ny) {
+ return true
+ }
+
+ // 回溯
+ path = path[:len(path)-1]
+ }
+ }
+
+ return false
+ }
+
+ // 开始搜索
+ if dfs(start.X, start.Y) {
+ // 标记路径
+ for i := 1; i < len(path)-1; i++ { // 跳过入口和出口
+ point := path[i]
+ m.Map[point.X][point.Y] = MapStep
+ }
+ fmt.Println("迷宫路径已找到并标记")
+ } else {
+ fmt.Println("未找到可行的迷宫路径")
+ }
+}
+
+func (m *Maze) PrintMaze() {
+ for j := 0; j < m.MapSize.Height+2; j++ {
+ for i := 0; i < m.MapSize.Width+2; i++ {
+ if m.Map[i][j] == MapWall {
+ fmt.Print("\x1b[43m \x1b[0m")
+ } else if m.Map[i][j] == MapGround {
+ fmt.Print(" ")
+ } else if m.Map[i][j] == MapOutside {
+ fmt.Print("\x1b[44m \x1b[0m")
+ } else if m.Map[i][j] == MapEntrance {
+ fmt.Print("\x1b[42m \x1b[0m")
+ } else if m.Map[i][j] == MapExit {
+ fmt.Print("\x1b[41m \x1b[0m")
+ } else if m.Map[i][j] == MapStep {
+ fmt.Print("\x1b[45m \x1b[0m")
+ }
+ }
+ fmt.Println()
+ }
+}
diff --git a/external_tools/tiger/main.go b/external_tools/tiger/main.go
index f5da862..d18565f 100644
--- a/external_tools/tiger/main.go
+++ b/external_tools/tiger/main.go
@@ -6,163 +6,27 @@ import (
"os"
"os/exec"
"strings"
+ "text/template"
"time"
"github.com/karldoenitz/Tigo/web"
)
-const (
- DemoCode = `package main
-
-import (
- "github.com/karldoenitz/Tigo/web"
-)
-
-// HelloHandler it's a demo handler
-type HelloHandler struct {
- web.BaseHandler
-}
-
-// Get http get method
-func (h *HelloHandler) Get() {
- // write your code here
- h.ResponseAsHtml("Hello Tiger Go!")
-}
-
-// urls url mapping
-var urls = []web.Pattern{
- {"/hello-world", HelloHandler{}, nil},
-}
-
-func main() {
- application := web.Application{
- IPAddress: "0.0.0.0",
- Port: 8888,
- UrlPatterns: urls,
- }
- application.Run()
-}
-`
- mainCode = `package main
-
-import (
- "github.com/karldoenitz/Tigo/web"
- "%s/handler"
-)
-
-// Write you url mapping here
-var urls = []web.Pattern{
- {"/ping", handler.PingHandler{}, nil},
+type TemplateData struct {
+ ProjectName string
+ PackageName string
+ HandlerName string
+ ConfigWorkDir string
}
-func main() {
- application := web.Application{
- IPAddress: "0.0.0.0",
- Port: 8080,
- UrlPatterns: urls,
- }
- application.Run()
-}
-
-`
- handlerCode = `// you can write your code here.
-// You can add 'Post', 'Put', 'Delete' and other methods to handler.
-package handler
-
-import (
- "github.com/karldoenitz/Tigo/web"
-)
-
-type %s struct {
- web.BaseHandler
-}
-
-func (p *%s) Get() {
- // write your code here
- p.ResponseAsText("Pong")
-}
-
-func (p *%s) Post() {
- // write your code here
- p.ResponseAsText("Pong")
-}
-
-`
- logCode = `// you can write your code here.
-// You can modify the log level and add more logs.
-package logger
-
-import (
- "os"
- "github.com/sirupsen/logrus"
-)
-
-var Logger = logrus.New()
-
-func init() {
- Logger.SetOutput(os.Stdout)
- Logger.SetLevel(logrus.InfoLevel)
+type HandlerTemplateData struct {
+ HandlerName string
}
-`
- configCodeJson = `{
- "cookie": "%s",
- "ip": "0.0.0.0",
- "port": 8080,
- "log": {
- "trace": "stdout",
- "info": "%s/log/tigo-framework-info.log",
- "warning": "%s/log/tigo-framework-warning.log",
- "error": "%s/log/tigo-framework-info-error.log"
- }
+type ConfigTemplateData struct {
+ CookieKey string
+ WorkDir string
}
-`
- configCodeYaml = `cookie: %s
-ip: 0.0.0.0
-port: 8080
-log:
- trace: stdout
- info: "%s/log/tigo-framework-info.log"
- warning: "%s/log/tigo-framework-warning.log"
- error: "%s/log/tigo-framework-info-error.log"
-`
- cmdVerbose = `
-use command tiger to create a Tigo projection.
-
-Usage:
-
- tiger [args]
-
-The commands are:
-
- addHandler to add a handler for Tigo projection
- create to create a Tigo projection
- conf to add a configuration for Tigo projection
- logger to add a logger for Tigo projection
- mod to run go mod
- version to show Tigo version
-
-Use "tiger help " for more information about a command.
-
-`
- cmdCreateVerbose = `
-use this command to create a Tigo project.
-"tiger create " can create a project with name "project_name",
-"tiger create demo" can create a demo project.
-
-`
- cmdConfVerbose = `
-use this command to add a configuration.
-if it's an empty folder, this command will throw an error.
-the new configuration will replace the old configuration.
-
-`
- cmdAddHandlerVerbose = `
-use this command to add a handler with defined name.
-"tiger addHandler " will add a handler named "handler_name".
-
-`
-)
// getWorkingDirPath 获取当前工作路径
func getWorkingDirPath() string {
@@ -251,10 +115,19 @@ func execCreate(arg string) {
defer func() {
_ = f.Close()
}()
- if _, err := f.WriteString(fmt.Sprintf(mainCode, arg)); err != nil {
- panic(err)
+
+ // 解析main模板
+ mainTmpl, err := template.New("main").Parse(mainCode)
+ if err != nil {
+ panic(fmt.Sprintf("main模板解析失败: %v", err))
+ }
+
+ // 执行main模板渲染
+ mainData := TemplateData{ProjectName: arg}
+ if err := mainTmpl.Execute(f, mainData); err != nil {
+ panic(fmt.Sprintf("main模板渲染失败: %v", err))
}
- // 创建handler文件
+
if err := os.Mkdir(projectPath+"/handler", os.ModePerm); err != nil {
fmt.Println(err.Error())
}
@@ -263,11 +136,24 @@ func execCreate(arg string) {
fmt.Println(err.Error())
return
}
- _, _ = fHandler.WriteString(fmt.Sprintf(handlerCode, "PingHandler", "PingHandler", "PingHandler"))
+
+ // 解析handler模板
+ handlerTmpl, err := template.New("handler").Parse(handlerCode)
+ if err != nil {
+ panic(fmt.Sprintf("handler模板解析失败: %v", err))
+ }
+
+ // 执行handler模板渲染
+ handlerData := HandlerTemplateData{HandlerName: "PingHandler"}
+ if err := handlerTmpl.Execute(fHandler, handlerData); err != nil {
+ panic(fmt.Sprintf("handler模板渲染失败: %v", err))
+ }
+
_ = f.Close()
_ = fHandler.Close()
fmt.Printf("project `%s` created successfully\n", arg)
+ fmt.Printf("execute command `cd %s` to enter the project directory\n", projectPath)
fmt.Println("Execute go mod")
}
@@ -307,7 +193,18 @@ func execAddHandler(handlerName string) {
fmt.Println(err.Error())
return
}
- _, _ = fHandler.WriteString(fmt.Sprintf(handlerCode, handlerName, handlerName, handlerName))
+
+ // 解析handler模板
+ handlerTmpl, err := template.New("handler").Parse(handlerCode)
+ if err != nil {
+ panic(fmt.Sprintf("handler模板解析失败: %v", err))
+ }
+
+ // 执行handler模板渲染
+ handlerData := HandlerTemplateData{HandlerName: handlerName}
+ if err := handlerTmpl.Execute(fHandler, handlerData); err != nil {
+ panic(fmt.Sprintf("handler模板渲染失败: %v", err))
+ }
_ = fHandler.Close()
// 判断是否有 main 文件
_, err = os.Stat(fmt.Sprintf("%s/main.go", workDir))
@@ -377,10 +274,31 @@ func execConf(arg string) {
return
}
currentTime := time.Now().String() + arg
+ // 准备配置模板数据
+ cookieKey := web.MD5m16(currentTime)
+ configData := ConfigTemplateData{
+ CookieKey: cookieKey,
+ WorkDir: workDir,
+ }
+
if strings.HasSuffix(arg, ".json") {
- _, _ = f.WriteString(fmt.Sprintf(configCodeJson, web.MD5m16(currentTime), workDir, workDir, workDir))
+ // 解析JSON配置模板
+ jsonTmpl, err := template.New("configJson").Parse(configCodeJson)
+ if err != nil {
+ panic(fmt.Sprintf("JSON配置模板解析失败: %v", err))
+ }
+ if err := jsonTmpl.Execute(f, configData); err != nil {
+ panic(fmt.Sprintf("JSON配置模板渲染失败: %v", err))
+ }
} else {
- _, _ = f.WriteString(fmt.Sprintf(configCodeYaml, web.MD5m16(currentTime), workDir, workDir, workDir))
+ // 解析YAML配置模板
+ yamlTmpl, err := template.New("configYaml").Parse(configCodeYaml)
+ if err != nil {
+ panic(fmt.Sprintf("YAML配置模板解析失败: %v", err))
+ }
+ if err := yamlTmpl.Execute(f, configData); err != nil {
+ panic(fmt.Sprintf("YAML配置模板渲染失败: %v", err))
+ }
}
_ = f.Close()
content, err := os.ReadFile(fmt.Sprintf("%s/main.go", workDir))
diff --git a/web/enums.go b/web/enums.go
index f9217a2..9a7762b 100644
--- a/web/enums.go
+++ b/web/enums.go
@@ -1,6 +1,6 @@
package web
-const Version = "2.0.0"
+const Version = "2.0.2"
const (
httpLowerGet = "get"