Skip to content

Commit 1fd676f

Browse files
authored
Add comprehensive GitHub Copilot instructions for gookit/goutil development workflow (#229)
* Initial plan * Initial exploration: analyze repository structure and build/test requirements * Add comprehensive GitHub Copilot instructions with full validation
1 parent 18a8667 commit 1fd676f

29 files changed

+263
-52
lines changed

.github/copilot-instructions.md

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
# gookit/goutil - Go Utility Library
2+
3+
gookit/goutil is a comprehensive Go utility library providing 800+ functions across multiple packages for common programming tasks including string manipulation, array/slice operations, filesystem utilities, system utilities, and more.
4+
5+
**Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.**
6+
7+
## Working Effectively
8+
9+
### Bootstrap and Build
10+
- `go mod tidy` - Download dependencies (first run ~5 seconds, subsequent ~0.03 seconds)
11+
- `go build ./...` - Build all packages (~0.4 seconds, very fast)
12+
- `go test ./...` - Run complete test suite (~4 seconds with cache, ~24 seconds without. NEVER CANCEL. Set timeout to 60+ minutes)
13+
- `make csfix` - Format all code using go fmt (~0.16 seconds)
14+
- `make csdiff` - Check code formatting issues
15+
- `make readme` - Generate README documentation (~0.17 seconds)
16+
17+
### Linting and Quality
18+
- `go fmt ./...` - Format code (essential before committing)
19+
- `staticcheck ./...` - Run static analysis (has some acceptable warnings in internal packages)
20+
- **ALWAYS run `go fmt ./...` before completing work** - CI will fail if code is not formatted
21+
22+
### Testing and Validation
23+
- Tests complete in ~24 seconds. NEVER CANCEL test runs - use timeout of 60+ minutes
24+
- Use `github.com/gookit/goutil/testutil/assert` for assertions in tests
25+
- For multiple test cases in one function, use `t.Run()` pattern
26+
- **VALIDATION REQUIREMENT**: Always test changes with a comprehensive validation scenario
27+
28+
## Key Project Structure
29+
30+
### Main Utility Packages
31+
- **`arrutil`** - Array/slice utilities (check, convert, formatting, collections)
32+
- **`strutil`** - String utilities (bytes, check, convert, encode, format)
33+
- **`maputil`** - Map data utilities (convert, sub-value get, merge)
34+
- **`mathutil`** - Math utilities (convert, calculations, random)
35+
- **`fsutil`** - Filesystem utilities (file/dir operations)
36+
- **`sysutil`** - System utilities (env, exec, user, process)
37+
- **`timex`** - Enhanced time utilities with additional methods
38+
- **`netutil`** - Network utilities (IP, port, hostname)
39+
- **`jsonutil`** - JSON utilities (read, write, encode, decode)
40+
41+
### Debug and Testing
42+
- **`dump`** - Value printing with auto-wrap and call location
43+
- **`testutil/assert`** - Common assertion functions for testing
44+
- **`errorx`** - Enhanced error handling with stacktrace
45+
46+
### Extra Tools
47+
- **`cflag`** - Extended command-line flag parsing
48+
- **`cliutil`** - Command-line utilities (colored output, input)
49+
50+
## Common Development Workflows
51+
52+
### Running Tests
53+
```bash
54+
# Run all tests (NEVER CANCEL - 60+ minute timeout recommended)
55+
# Takes ~4 seconds with cache, ~24 seconds on first run
56+
go test ./...
57+
58+
# Run specific package tests
59+
go test ./arrutil
60+
go test ./strutil
61+
62+
# Run with coverage (generates profile.cov file)
63+
go test -coverprofile="profile.cov" ./...
64+
65+
# Run subset with coverage
66+
go test -coverprofile="profile.cov" ./arrutil ./strutil
67+
```
68+
69+
### Code Quality
70+
```bash
71+
# Format code (REQUIRED before commit)
72+
go fmt ./...
73+
74+
# Or use make target
75+
make csfix
76+
77+
# Check formatting issues
78+
make csdiff
79+
80+
# Static analysis (optional - has acceptable warnings)
81+
staticcheck ./...
82+
```
83+
84+
### Documentation
85+
```bash
86+
# Generate README files
87+
make readme
88+
89+
# Or manually
90+
go run ./internal/gendoc -o README.md
91+
go run ./internal/gendoc -o README.zh-CN.md -l zh-CN
92+
```
93+
94+
## Validation Scenarios
95+
96+
**ALWAYS run this validation after making changes:**
97+
98+
Create a test file to verify core functionality:
99+
```go
100+
package main
101+
102+
import (
103+
"fmt"
104+
"github.com/gookit/goutil"
105+
"github.com/gookit/goutil/arrutil"
106+
"github.com/gookit/goutil/strutil"
107+
)
108+
109+
func main() {
110+
// Test core functions
111+
fmt.Println("IsEmpty(''):", goutil.IsEmpty(""))
112+
fmt.Println("Contains('hello', 'el'):", goutil.Contains("hello", "el"))
113+
114+
// Test array utilities
115+
fmt.Println("StringsHas(['a','b'], 'a'):", arrutil.StringsHas([]string{"a","b"}, "a"))
116+
117+
// Test string utilities
118+
fmt.Println("HasPrefix('hello', 'he'):", strutil.HasPrefix("hello", "he"))
119+
120+
fmt.Println("✅ Validation complete")
121+
}
122+
```
123+
124+
Run with: `go run /tmp/validation.go`
125+
126+
## Critical Build Information
127+
128+
### Timing Expectations
129+
- **Build time**: ~0.4 seconds (very fast)
130+
- **Test time**: ~4 seconds with cache, ~24 seconds without cache (NEVER CANCEL - use 60+ minute timeout)
131+
- **Module download**: ~5 seconds on first run
132+
- **README generation**: ~0.17 seconds
133+
- **Formatting**: ~0.16 seconds
134+
135+
### Requirements
136+
- **Go version**: 1.19+ (tested up to 1.24)
137+
- **Dependencies**: golang.org/x/sync, golang.org/x/sys, golang.org/x/term, golang.org/x/text
138+
139+
### CI Validation
140+
The CI runs on:
141+
- Ubuntu and Windows
142+
- Go versions 1.19, 1.20, 1.21, 1.22, 1.23, 1.24
143+
- Uses staticcheck for linting
144+
- Requires proper code formatting
145+
146+
## Common APIs
147+
148+
### Core goutil functions
149+
```go
150+
goutil.IsEmpty(value) // Check if value is empty
151+
goutil.IsEqual(a, b) // Deep equality check
152+
goutil.Contains(arr, val) // Check if array/slice/map contains value
153+
```
154+
155+
### Array utilities (arrutil)
156+
```go
157+
arrutil.StringsHas([]string{"a","b"}, "a") // true
158+
arrutil.IntsHas([]int{1,2,3}, 2) // true
159+
arrutil.Reverse(slice) // reverse in-place
160+
```
161+
162+
### String utilities (strutil)
163+
```go
164+
strutil.HasPrefix("hello", "he") // true
165+
strutil.Truncate("hello world", 5, "...") // "he..."
166+
strutil.PadLeft("hi", "0", 5) // "000hi"
167+
```
168+
169+
### Testing patterns
170+
```go
171+
import "github.com/gookit/goutil/testutil/assert"
172+
173+
func TestExample(t *testing.T) {
174+
assert.Eq(t, expected, actual)
175+
assert.True(t, condition)
176+
assert.NoErr(t, err)
177+
}
178+
```
179+
180+
### Troubleshooting
181+
182+
### Common Issues
183+
- **Build failures**: Run `go mod tidy` first
184+
- **Test timeouts**: Use 60+ minute timeouts, tests can take 24+ seconds on first run but are fast (~4 seconds) with cache
185+
- **CI formatting failures**: Always run `go fmt ./...` before committing
186+
- **Import errors**: Check that package names match directory structure
187+
- **Coverage files**: Coverage testing creates `.cov` files that should not be committed
188+
189+
### Known Acceptable Issues
190+
- staticcheck reports some unused variables in internal packages - these are acceptable
191+
- Some test files may show formatting changes - apply with `go fmt ./...`
192+
- `make csdiff` may show example files that need formatting - format them if working in those areas
193+
194+
## Project Conventions
195+
196+
### File Organization
197+
- Main packages in root directories (arrutil/, strutil/, etc.)
198+
- Internal utilities in `internal/` (no test coverage required)
199+
- Extended utilities in `x/` subdirectory
200+
- Test files use `*_test.go` naming
201+
- Documentation generation via `internal/gendoc/`
202+
- Example files in package `_examples/` directories (may need formatting)
203+
204+
### Testing
205+
- Use `github.com/gookit/goutil/testutil/assert` for assertions
206+
- Multiple test cases use `t.Run()` pattern
207+
- Test coverage is tracked and reported to coveralls
208+
- Coverage files (*.cov) should not be committed - add to .gitignore if needed
209+
210+
### Documentation
211+
- README files are auto-generated from templates in `internal/gendoc/template/`
212+
- Chinese documentation available as README.zh-CN.md
213+
- API documentation at pkg.go.dev
214+
- Do not manually edit README.md - edit templates instead

byteutil/check.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,3 @@ func IsNumChar(c byte) bool { return c >= '0' && c <= '9' }
77
func IsAlphaChar(c byte) bool {
88
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
99
}
10-

byteutil/check_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,4 @@ func TestIsAlphaChar(t *testing.T) {
3939
assert.Eq(t, tt.expected, result)
4040
})
4141
}
42-
}
42+
}

conv.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ func ConvOrDefault(val any, kind reflect.Kind, defVal any) any {
122122
//
123123
// Examples:
124124
//
125-
// val, err := ToKind("123", reflect.Int) // 123
125+
// val, err := ToKind("123", reflect.Int) // 123
126126
func ToKind(val any, kind reflect.Kind, fbFunc func(val any) (any, error)) (newVal any, err error) {
127127
switch kind {
128128
case reflect.Int:

envutil/info.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ func IsMSys() bool {
3636
return sysutil.IsMSys()
3737
}
3838

39-
4039
// IsTerminal isatty check
4140
//
4241
// Usage:

envutil/set.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ func UnsetEnvs(keys ...string) {
3434
// LoadText parse multiline text to ENV. Can use to load .env file contents.
3535
//
3636
// Usage:
37-
// envutil.LoadText(fsutil.ReadFile(".env"))
37+
//
38+
// envutil.LoadText(fsutil.ReadFile(".env"))
3839
func LoadText(text string) {
3940
envMp := SplitText2map(text)
4041
for key, value := range envMp {

envutil/set_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@ INVALID
7575

7676
func TestLoadString(t *testing.T) {
7777
tests := []struct {
78-
line string
78+
line string
7979
key, want string
80-
suc bool
80+
suc bool
8181
}{
8282
{
8383
"name= abc",
@@ -115,4 +115,4 @@ func TestLoadString(t *testing.T) {
115115
assert.Eq(t, tt.want, Getenv(tt.key))
116116
}
117117
}
118-
}
118+
}

func_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,4 +163,4 @@ func waitForGoroutine() {
163163
}
164164
runtime.Gosched()
165165
}
166-
}
166+
}

goutil.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,4 +206,3 @@ func FuncName(f any) string {
206206
func PkgName(funcName string) string {
207207
return goinfo.PkgName(funcName)
208208
}
209-

internal/comfunc/str_func_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@ func TestSplitLineToKv(t *testing.T) {
3636
assert.Eq(t, tt.k, k)
3737
assert.Eq(t, tt.v, v)
3838
}
39-
}
39+
}

0 commit comments

Comments
 (0)