Skip to content

Commit ccff149

Browse files
committed
feat: Support config in user home path .codei18n
--story=1
1 parent 53a2428 commit ccff149

File tree

4 files changed

+91
-17
lines changed

4 files changed

+91
-17
lines changed

adapters/rust/adapter.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package rust
22

33
import (
44
"context"
5+
"os"
56

67
sitter "github.com/smacker/go-tree-sitter"
78
"github.com/smacker/go-tree-sitter/rust"
@@ -31,6 +32,14 @@ func (a *RustAdapter) Language() string {
3132
// It returns a list of domain.Comment structs containing comment text, position, and context symbol.
3233
// If src is nil, it currently expects the caller to handle file reading (TODO: implement file reading).
3334
func (a *RustAdapter) Parse(file string, src []byte) ([]*domain.Comment, error) {
35+
if src == nil {
36+
data, err := os.ReadFile(file)
37+
if err != nil {
38+
return nil, err
39+
}
40+
src = data
41+
}
42+
3443
// Parse the source code using Tree-sitter
3544
tree, err := a.parser.ParseCtx(context.Background(), nil, src)
3645
if err != nil {

adapters/rust/extractor.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ func (a *RustAdapter) extractComments(root *sitter.Node, src []byte, file string
3232
node := c.Node
3333
content := node.Content(src)
3434

35+
if isEmptyComment(content) {
36+
continue
37+
}
38+
3539
// Find Owner and Symbol Path
3640
owner := FindOwnerNode(node, src)
3741
symbolPath := ResolveSymbolPath(owner, src)
@@ -67,3 +71,23 @@ func getDomainCommentType(content string) domain.CommentType {
6771
}
6872
return domain.CommentTypeLine
6973
}
74+
75+
func isEmptyComment(content string) bool {
76+
trimmed := strings.TrimSpace(content)
77+
switch {
78+
case strings.HasPrefix(trimmed, "///"):
79+
return strings.TrimSpace(strings.TrimPrefix(trimmed, "///")) == ""
80+
case strings.HasPrefix(trimmed, "//!"):
81+
return strings.TrimSpace(strings.TrimPrefix(trimmed, "//!")) == ""
82+
case strings.HasPrefix(trimmed, "//"):
83+
return strings.TrimSpace(strings.TrimPrefix(trimmed, "//")) == ""
84+
case strings.HasPrefix(trimmed, "/*"):
85+
inner := strings.TrimPrefix(trimmed, "/*")
86+
if strings.HasSuffix(inner, "*/") {
87+
inner = strings.TrimSuffix(inner, "*/")
88+
}
89+
return strings.TrimSpace(inner) == ""
90+
default:
91+
return strings.TrimSpace(trimmed) == ""
92+
}
93+
}

cmd/codei18n/root.go

Lines changed: 55 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package main
33
import (
44
"fmt"
55
"os"
6+
"path/filepath"
67

78
"github.com/spf13/cobra"
89
"github.com/spf13/viper"
@@ -37,7 +38,7 @@ func init() {
3738
rootCmd.SetVersionTemplate("CodeI18n CLI 版本: {{.Version}}\n")
3839

3940
// Global flags
40-
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "配置文件路径 (默认是 $HOME/.codei18n.json 或项目根目录 .codei18n/config.json)")
41+
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "配置文件路径 (默认读取 ~/.codei18n/config.json 以及当前目录的 .codei18n/config.json)")
4142
rootCmd.PersistentFlags().BoolVar(&verbose, "verbose", false, "显示详细日志")
4243

4344
// Bind flags to viper
@@ -46,31 +47,69 @@ func init() {
4647

4748
// initConfig reads in config file and ENV variables if set.
4849
func initConfig() {
50+
viper.AutomaticEnv() // read in environment variables that match
51+
4952
if cfgFile != "" {
50-
// Use config file from the flag.
5153
viper.SetConfigFile(cfgFile)
52-
} else {
53-
// Find home directory.
54-
home, err := os.UserHomeDir()
55-
if err != nil {
54+
if err := viper.ReadInConfig(); err != nil {
5655
cobra.CheckErr(err)
5756
}
57+
if verbose {
58+
fmt.Fprintf(os.Stderr, "Using config file: %s\n", viper.ConfigFileUsed())
59+
}
60+
return
61+
}
5862

59-
// Search config in home directory with name ".codei18n" (without extension).
60-
viper.AddConfigPath(home)
61-
viper.AddConfigPath(".codei18n")
62-
viper.SetConfigType("json")
63-
viper.SetConfigName("config")
63+
home, err := os.UserHomeDir()
64+
if err != nil {
65+
cobra.CheckErr(err)
6466
}
6567

66-
viper.AutomaticEnv() // read in environment variables that match
68+
configLoaded := false
69+
70+
if loaded, err := loadConfigFile(filepath.Join(home, ".codei18n", "config.json"), false); err != nil {
71+
cobra.CheckErr(err)
72+
} else if loaded {
73+
configLoaded = true
74+
}
75+
76+
if loaded, err := loadConfigFile(filepath.Join(".codei18n", "config.json"), configLoaded); err != nil {
77+
cobra.CheckErr(err)
78+
} else if loaded {
79+
configLoaded = true
80+
}
81+
82+
if !configLoaded && verbose {
83+
fmt.Fprintln(os.Stderr, "未找到配置文件,使用内置默认配置")
84+
}
85+
}
6786

68-
// If a config file is found, read it in.
69-
if err := viper.ReadInConfig(); err == nil && verbose {
70-
fmt.Fprintf(os.Stderr, "Using config file: %s\n", viper.ConfigFileUsed())
87+
func loadConfigFile(path string, merge bool) (bool, error) {
88+
if _, err := os.Stat(path); err != nil {
89+
if os.IsNotExist(err) {
90+
return false, nil
91+
}
92+
return false, err
7193
}
94+
95+
viper.SetConfigFile(path)
96+
97+
var err error
98+
if merge {
99+
err = viper.MergeInConfig()
100+
} else {
101+
err = viper.ReadInConfig()
102+
}
103+
if err != nil {
104+
return false, err
105+
}
106+
107+
if verbose {
108+
fmt.Fprintf(os.Stderr, "Using config file: %s\n", path)
109+
}
110+
return true, nil
72111
}
73112

74113
func main() {
75114
Execute()
76-
}
115+
}

core/mapping/store.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"encoding/json"
55
"os"
66
"path/filepath"
7+
"strings"
78
"sync"
89

910
"github.com/studyzy/codei18n/core/domain"
@@ -99,7 +100,8 @@ func (s *Store) Set(id, lang, text string) {
99100
if _, ok := s.mapping.Comments[id]; !ok {
100101
s.mapping.Comments[id] = make(map[string]string)
101102
}
102-
s.mapping.Comments[id][lang] = text
103+
cleanText := strings.TrimRight(text, "\r\n")
104+
s.mapping.Comments[id][lang] = cleanText
103105
}
104106

105107
// GetMapping returns the underlying mapping object (read-only copy recommended for complex ops)

0 commit comments

Comments
 (0)