freelang-v4 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (261) hide show
  1. package/README.md +548 -0
  2. package/dist/ast.d.ts +367 -0
  3. package/dist/ast.js +4 -0
  4. package/dist/ast.js.map +1 -0
  5. package/dist/async-basic.test.d.ts +1 -0
  6. package/dist/async-basic.test.js +88 -0
  7. package/dist/async-basic.test.js.map +1 -0
  8. package/dist/async-jest.test.d.ts +1 -0
  9. package/dist/async-jest.test.js +99 -0
  10. package/dist/async-jest.test.js.map +1 -0
  11. package/dist/channel-jest.test.d.ts +1 -0
  12. package/dist/channel-jest.test.js +148 -0
  13. package/dist/channel-jest.test.js.map +1 -0
  14. package/dist/checker-jest.test.d.ts +1 -0
  15. package/dist/checker-jest.test.js +160 -0
  16. package/dist/checker-jest.test.js.map +1 -0
  17. package/dist/checker.d.ts +149 -0
  18. package/dist/checker.js +1565 -0
  19. package/dist/checker.js.map +1 -0
  20. package/dist/checker.test.d.ts +1 -0
  21. package/dist/checker.test.js +217 -0
  22. package/dist/checker.test.js.map +1 -0
  23. package/dist/compiler-jest.test.d.ts +1 -0
  24. package/dist/compiler-jest.test.js +233 -0
  25. package/dist/compiler-jest.test.js.map +1 -0
  26. package/dist/compiler.d.ts +127 -0
  27. package/dist/compiler.js +1588 -0
  28. package/dist/compiler.js.map +1 -0
  29. package/dist/compiler.test.d.ts +1 -0
  30. package/dist/compiler.test.js +313 -0
  31. package/dist/compiler.test.js.map +1 -0
  32. package/dist/db-100m-full.d.ts +5 -0
  33. package/dist/db-100m-full.js +78 -0
  34. package/dist/db-100m-full.js.map +1 -0
  35. package/dist/db-100m-no-index.d.ts +12 -0
  36. package/dist/db-100m-no-index.js +119 -0
  37. package/dist/db-100m-no-index.js.map +1 -0
  38. package/dist/db-100m-real.d.ts +5 -0
  39. package/dist/db-100m-real.js +131 -0
  40. package/dist/db-100m-real.js.map +1 -0
  41. package/dist/db-100m-streaming.d.ts +15 -0
  42. package/dist/db-100m-streaming.js +164 -0
  43. package/dist/db-100m-streaming.js.map +1 -0
  44. package/dist/db-100m-test.d.ts +5 -0
  45. package/dist/db-100m-test.js +111 -0
  46. package/dist/db-100m-test.js.map +1 -0
  47. package/dist/db-jest.test.d.ts +1 -0
  48. package/dist/db-jest.test.js +182 -0
  49. package/dist/db-jest.test.js.map +1 -0
  50. package/dist/db-runtime.d.ts +24 -0
  51. package/dist/db-runtime.js +204 -0
  52. package/dist/db-runtime.js.map +1 -0
  53. package/dist/db.d.ts +249 -0
  54. package/dist/db.js +593 -0
  55. package/dist/db.js.map +1 -0
  56. package/dist/file-io-jest.test.d.ts +1 -0
  57. package/dist/file-io-jest.test.js +225 -0
  58. package/dist/file-io-jest.test.js.map +1 -0
  59. package/dist/for-of-jest.test.d.ts +1 -0
  60. package/dist/for-of-jest.test.js +230 -0
  61. package/dist/for-of-jest.test.js.map +1 -0
  62. package/dist/for-of.test.d.ts +1 -0
  63. package/dist/for-of.test.js +305 -0
  64. package/dist/for-of.test.js.map +1 -0
  65. package/dist/function-literal-jest.test.d.ts +1 -0
  66. package/dist/function-literal-jest.test.js +180 -0
  67. package/dist/function-literal-jest.test.js.map +1 -0
  68. package/dist/function-literal.test.d.ts +1 -0
  69. package/dist/function-literal.test.js +245 -0
  70. package/dist/function-literal.test.js.map +1 -0
  71. package/dist/generics-jest.test.d.ts +1 -0
  72. package/dist/generics-jest.test.js +93 -0
  73. package/dist/generics-jest.test.js.map +1 -0
  74. package/dist/ir-gen.d.ts +15 -0
  75. package/dist/ir-gen.js +400 -0
  76. package/dist/ir-gen.js.map +1 -0
  77. package/dist/ir.d.ts +114 -0
  78. package/dist/ir.js +5 -0
  79. package/dist/ir.js.map +1 -0
  80. package/dist/lexer.d.ts +110 -0
  81. package/dist/lexer.js +467 -0
  82. package/dist/lexer.js.map +1 -0
  83. package/dist/lexer.test.d.ts +1 -0
  84. package/dist/lexer.test.js +426 -0
  85. package/dist/lexer.test.js.map +1 -0
  86. package/dist/main.d.ts +2 -0
  87. package/dist/main.js +241 -0
  88. package/dist/main.js.map +1 -0
  89. package/dist/module-jest.test.d.ts +1 -0
  90. package/dist/module-jest.test.js +123 -0
  91. package/dist/module-jest.test.js.map +1 -0
  92. package/dist/parser.d.ts +56 -0
  93. package/dist/parser.js +1060 -0
  94. package/dist/parser.js.map +1 -0
  95. package/dist/parser.test.d.ts +1 -0
  96. package/dist/parser.test.js +461 -0
  97. package/dist/parser.test.js.map +1 -0
  98. package/dist/pattern-matching-jest.test.d.ts +1 -0
  99. package/dist/pattern-matching-jest.test.js +158 -0
  100. package/dist/pattern-matching-jest.test.js.map +1 -0
  101. package/dist/pkg/init.d.ts +1 -0
  102. package/dist/pkg/init.js +118 -0
  103. package/dist/pkg/init.js.map +1 -0
  104. package/dist/pkg/install.d.ts +1 -0
  105. package/dist/pkg/install.js +77 -0
  106. package/dist/pkg/install.js.map +1 -0
  107. package/dist/pkg/registry.d.ts +23 -0
  108. package/dist/pkg/registry.js +106 -0
  109. package/dist/pkg/registry.js.map +1 -0
  110. package/dist/pkg/run.d.ts +1 -0
  111. package/dist/pkg/run.js +76 -0
  112. package/dist/pkg/run.js.map +1 -0
  113. package/dist/pkg/toml.d.ts +5 -0
  114. package/dist/pkg/toml.js +117 -0
  115. package/dist/pkg/toml.js.map +1 -0
  116. package/dist/repl.d.ts +15 -0
  117. package/dist/repl.js +197 -0
  118. package/dist/repl.js.map +1 -0
  119. package/dist/runtime/bytecode.d.ts +92 -0
  120. package/dist/runtime/bytecode.js +253 -0
  121. package/dist/runtime/bytecode.js.map +1 -0
  122. package/dist/runtime/value.d.ts +102 -0
  123. package/dist/runtime/value.js +302 -0
  124. package/dist/runtime/value.js.map +1 -0
  125. package/dist/runtime/vm.d.ts +65 -0
  126. package/dist/runtime/vm.js +293 -0
  127. package/dist/runtime/vm.js.map +1 -0
  128. package/dist/struct-instance-jest.test.d.ts +1 -0
  129. package/dist/struct-instance-jest.test.js +209 -0
  130. package/dist/struct-instance-jest.test.js.map +1 -0
  131. package/dist/struct-instance.test.d.ts +1 -0
  132. package/dist/struct-instance.test.js +291 -0
  133. package/dist/struct-instance.test.js.map +1 -0
  134. package/dist/struct-jest.test.d.ts +1 -0
  135. package/dist/struct-jest.test.js +176 -0
  136. package/dist/struct-jest.test.js.map +1 -0
  137. package/dist/struct.test.d.ts +1 -0
  138. package/dist/struct.test.js +231 -0
  139. package/dist/struct.test.js.map +1 -0
  140. package/dist/trait-jest.test.d.ts +1 -0
  141. package/dist/trait-jest.test.js +120 -0
  142. package/dist/trait-jest.test.js.map +1 -0
  143. package/dist/vm-jest.test.d.ts +1 -0
  144. package/dist/vm-jest.test.js +569 -0
  145. package/dist/vm-jest.test.js.map +1 -0
  146. package/dist/vm.d.ts +81 -0
  147. package/dist/vm.js +1956 -0
  148. package/dist/vm.js.map +1 -0
  149. package/dist/vm.test.d.ts +1 -0
  150. package/dist/vm.test.js +337 -0
  151. package/dist/vm.test.js.map +1 -0
  152. package/dist/web-repl/sandbox.d.ts +11 -0
  153. package/dist/web-repl/sandbox.js +76 -0
  154. package/dist/web-repl/sandbox.js.map +1 -0
  155. package/dist/web-repl/server.d.ts +1 -0
  156. package/dist/web-repl/server.js +111 -0
  157. package/dist/web-repl/server.js.map +1 -0
  158. package/dist/while-loop-jest.test.d.ts +1 -0
  159. package/dist/while-loop-jest.test.js +201 -0
  160. package/dist/while-loop-jest.test.js.map +1 -0
  161. package/dist/while-loop.test.d.ts +1 -0
  162. package/dist/while-loop.test.js +262 -0
  163. package/dist/while-loop.test.js.map +1 -0
  164. package/docs/EXPERIENCE.md +787 -0
  165. package/docs/README.md +175 -0
  166. package/docs/V1_V2_V3_ANALYSIS.md +107 -0
  167. package/docs/_config.yml +36 -0
  168. package/docs/api-reference.md +459 -0
  169. package/docs/architecture.md +470 -0
  170. package/docs/benchmarks.md +295 -0
  171. package/docs/comparison.md +454 -0
  172. package/docs/index.md +335 -0
  173. package/docs/language-completeness.md +228 -0
  174. package/docs/learning-guide.md +651 -0
  175. package/package.json +65 -0
  176. package/src/api/deploy_key.fl +294 -0
  177. package/src/api/issue.fl +302 -0
  178. package/src/api/org.fl +356 -0
  179. package/src/api/repo.fl +394 -0
  180. package/src/api/team.fl +299 -0
  181. package/src/api/user.fl +385 -0
  182. package/src/api/webhook.fl +273 -0
  183. package/src/ast.ts +158 -0
  184. package/src/async-basic.test.ts +94 -0
  185. package/src/async-jest.test.ts +107 -0
  186. package/src/channel-jest.test.ts +158 -0
  187. package/src/checker-jest.test.ts +189 -0
  188. package/src/checker.test.ts +279 -0
  189. package/src/checker.ts +1861 -0
  190. package/src/commands/analyze.fl +227 -0
  191. package/src/commands/auth.fl +315 -0
  192. package/src/commands/batch.fl +349 -0
  193. package/src/commands/config.fl +199 -0
  194. package/src/commands/deploy_key.fl +352 -0
  195. package/src/commands/issue.fl +275 -0
  196. package/src/commands/main.fl +492 -0
  197. package/src/commands/org.fl +425 -0
  198. package/src/commands/repo.fl +581 -0
  199. package/src/commands/team.fl +244 -0
  200. package/src/commands/user.fl +423 -0
  201. package/src/commands/webhook.fl +400 -0
  202. package/src/compiler-jest.test.ts +275 -0
  203. package/src/compiler.test.ts +375 -0
  204. package/src/compiler.ts +1770 -0
  205. package/src/config.fl +175 -0
  206. package/src/core/batch.fl +355 -0
  207. package/src/core/cache.fl +284 -0
  208. package/src/core/ensure.fl +324 -0
  209. package/src/db-100m-full.ts +96 -0
  210. package/src/db-100m-no-index.ts +133 -0
  211. package/src/db-100m-real.ts +152 -0
  212. package/src/db-100m-streaming.ts +154 -0
  213. package/src/db-100m-test.ts +136 -0
  214. package/src/db-jest.test.ts +161 -0
  215. package/src/db-runtime.ts +242 -0
  216. package/src/db.ts +676 -0
  217. package/src/errors.fl +134 -0
  218. package/src/for-of-jest.test.ts +246 -0
  219. package/src/for-of.test.ts +308 -0
  220. package/src/function-literal-jest.test.ts +193 -0
  221. package/src/function-literal.test.ts +248 -0
  222. package/src/generics-jest.test.ts +104 -0
  223. package/src/http/client.fl +327 -0
  224. package/src/ir-gen.ts +459 -0
  225. package/src/ir.ts +80 -0
  226. package/src/lexer.test.ts +499 -0
  227. package/src/lexer.ts +522 -0
  228. package/src/main.ts +223 -0
  229. package/src/models.fl +162 -0
  230. package/src/module-jest.test.ts +145 -0
  231. package/src/parser.test.ts +542 -0
  232. package/src/parser.ts +1211 -0
  233. package/src/pattern-matching-jest.test.ts +170 -0
  234. package/src/pkg/init.ts +91 -0
  235. package/src/pkg/install.ts +56 -0
  236. package/src/pkg/registry.ts +103 -0
  237. package/src/pkg/run.ts +49 -0
  238. package/src/pkg/toml.ts +129 -0
  239. package/src/repl.ts +190 -0
  240. package/src/runtime/bytecode.ts +291 -0
  241. package/src/runtime/value.ts +322 -0
  242. package/src/runtime/vm.ts +354 -0
  243. package/src/self-host/bootstrap.fl +68 -0
  244. package/src/self-host/interpreter.fl +361 -0
  245. package/src/self-host/lexer-simple.fl +22 -0
  246. package/src/self-host/lexer.fl +305 -0
  247. package/src/self-host/parser.fl +580 -0
  248. package/src/struct-instance-jest.test.ts +221 -0
  249. package/src/struct-instance.test.ts +293 -0
  250. package/src/struct-jest.test.ts +187 -0
  251. package/src/struct.test.ts +234 -0
  252. package/src/trait-jest.test.ts +136 -0
  253. package/src/vm-jest.test.ts +754 -0
  254. package/src/vm.ts +1976 -0
  255. package/src/web-repl/public/index.html +50 -0
  256. package/src/web-repl/public/main.js +105 -0
  257. package/src/web-repl/public/style.css +225 -0
  258. package/src/web-repl/sandbox.ts +88 -0
  259. package/src/web-repl/server.ts +97 -0
  260. package/src/while-loop-jest.test.ts +218 -0
  261. package/src/while-loop.test.ts +267 -0
@@ -0,0 +1,349 @@
1
+ // FreeLang v4.2 — gogs-cli Phase 5 배치 명령어
2
+ // create, ensure, delete 구현 (병렬 처리)
3
+ // 300라인
4
+
5
+ /// 배치 생성
6
+ /// gogs batch create REPOS_FILE.yaml [--parallel 10] [--skip-existing]
7
+ async fn cmd_batch_create(args: CliArgs) -> CliResult {
8
+ // 1. 인자 검증
9
+ var file_path = get_positional(args, 0)
10
+ if file_path == "" {
11
+ return CliResult {
12
+ exit_code: 1,
13
+ output: "",
14
+ error: "Repository file (YAML) is required"
15
+ }
16
+ }
17
+
18
+ // 2. 플래그 파싱
19
+ var parallel_str = get_flag(args, "parallel")
20
+ var parallel = if parallel_str != "" then parse_int(parallel_str) else 5
21
+ var skip_existing = has_flag(args, "skip-existing")
22
+
23
+ // 3. 설정 로드
24
+ var host = await get_default_host()
25
+ if host.url == "" {
26
+ return CliResult {
27
+ exit_code: 1,
28
+ output: "",
29
+ error: "Not logged in"
30
+ }
31
+ }
32
+
33
+ // 4. 파일 읽기
34
+ println("Reading repository file: " + file_path)
35
+
36
+ // TODO: read_file, parse_yaml 구현
37
+ // var content = read_file(file_path)
38
+ // var repos = parse_yaml(content)
39
+
40
+ // 5. 클라이언트 및 캐시
41
+ var client = new_client(host.url, host.token)
42
+ var cache = new_cache(300)
43
+
44
+ // 6. 배치 생성 (병렬)
45
+ println("Creating repositories (parallel: " + str(parallel) + ")...")
46
+
47
+ var repo_service = new_repo_service(client, cache)
48
+
49
+ // TODO: 배열 처리 및 병렬 실행
50
+ // var results = await batch_create_repos(repo_service, repos, parallel)
51
+
52
+ var output = ""
53
+ output = output + "✓ Batch create completed\n"
54
+ output = output + " Created: 0\n"
55
+ output = output + " Failed: 0\n"
56
+ output = output + " Skipped: 0\n"
57
+
58
+ CliResult {
59
+ exit_code: 0,
60
+ output: output,
61
+ error: ""
62
+ }
63
+ }
64
+
65
+ /// 배치 동기화 (멱등성)
66
+ /// gogs batch ensure DESIRED.yaml [--parallel 20]
67
+ async fn cmd_batch_ensure(args: CliArgs) -> CliResult {
68
+ // 1. 인자 검증
69
+ var file_path = get_positional(args, 0)
70
+ if file_path == "" {
71
+ return CliResult {
72
+ exit_code: 1,
73
+ output: "",
74
+ error: "Repository file (YAML) is required"
75
+ }
76
+ }
77
+
78
+ // 2. 플래그 파싱
79
+ var parallel_str = get_flag(args, "parallel")
80
+ var parallel = if parallel_str != "" then parse_int(parallel_str) else 10
81
+
82
+ // 3. 설정 로드
83
+ var host = await get_default_host()
84
+ if host.url == "" {
85
+ return CliResult {
86
+ exit_code: 1,
87
+ output: "",
88
+ error: "Not logged in"
89
+ }
90
+ }
91
+
92
+ // 4. 파일 읽기
93
+ println("Reading desired state: " + file_path)
94
+
95
+ // TODO: read_file, parse_yaml 구현
96
+ // var content = read_file(file_path)
97
+ // var desired_repos = parse_yaml(content)
98
+
99
+ // 5. 클라이언트 및 캐시
100
+ var client = new_client(host.url, host.token)
101
+ var cache = new_cache(300)
102
+
103
+ // 6. 현재 저장소 조회
104
+ println("Fetching current repositories...")
105
+ // var repo_service = new_repo_service(client, cache)
106
+ // var current_repos = await list_repos(repo_service)
107
+
108
+ // 7. 차이 계산 및 적용 (병렬)
109
+ println("Syncing repositories (parallel: " + str(parallel) + ")...")
110
+
111
+ var output = ""
112
+ output = output + "✓ Batch ensure completed\n"
113
+ output = output + " Created: 0\n"
114
+ output = output + " Updated: 0\n"
115
+ output = output + " Deleted: 0\n"
116
+ output = output + " Unchanged: 0\n"
117
+
118
+ CliResult {
119
+ exit_code: 0,
120
+ output: output,
121
+ error: ""
122
+ }
123
+ }
124
+
125
+ /// 배치 삭제
126
+ /// gogs batch delete REPOS.yaml [--parallel 10] [--force]
127
+ async fn cmd_batch_delete(args: CliArgs) -> CliResult {
128
+ // 1. 인자 검증
129
+ var file_path = get_positional(args, 0)
130
+ if file_path == "" {
131
+ return CliResult {
132
+ exit_code: 1,
133
+ output: "",
134
+ error: "Repository file (YAML) is required"
135
+ }
136
+ }
137
+
138
+ // 2. 플래그 파싱
139
+ var parallel_str = get_flag(args, "parallel")
140
+ var parallel = if parallel_str != "" then parse_int(parallel_str) else 5
141
+ var force = has_flag(args, "force")
142
+
143
+ if !force {
144
+ println("⚠️ This will delete all repositories in " + file_path)
145
+ println("Run with --force to confirm")
146
+ return CliResult {
147
+ exit_code: 1,
148
+ output: "",
149
+ error: "Deletion not confirmed"
150
+ }
151
+ }
152
+
153
+ // 3. 설정 로드
154
+ var host = await get_default_host()
155
+ if host.url == "" {
156
+ return CliResult {
157
+ exit_code: 1,
158
+ output: "",
159
+ error: "Not logged in"
160
+ }
161
+ }
162
+
163
+ // 4. 파일 읽기
164
+ println("Reading repository file: " + file_path)
165
+
166
+ // TODO: read_file, parse_yaml 구현
167
+ // var content = read_file(file_path)
168
+ // var repos = parse_yaml(content)
169
+
170
+ // 5. 클라이언트 및 캐시
171
+ var client = new_client(host.url, host.token)
172
+ var cache = new_cache(300)
173
+
174
+ // 6. 배치 삭제 (병렬)
175
+ println("Deleting repositories (parallel: " + str(parallel) + ")...")
176
+
177
+ var repo_service = new_repo_service(client, cache)
178
+
179
+ // TODO: 배열 처리 및 병렬 실행
180
+ // var results = await batch_delete_repos(repo_service, repos, parallel)
181
+
182
+ var output = ""
183
+ output = output + "✓ Batch delete completed\n"
184
+ output = output + " Deleted: 0\n"
185
+ output = output + " Failed: 0\n"
186
+
187
+ CliResult {
188
+ exit_code: 0,
189
+ output: output,
190
+ error: ""
191
+ }
192
+ }
193
+
194
+ // ==================== 배치 처리 유틸리티 ====================
195
+
196
+ /// 배치 결과 구조
197
+ struct BatchResult {
198
+ total: i32
199
+ success: i32
200
+ failed: i32
201
+ errors: [str]
202
+ }
203
+
204
+ /// 배치 진행 상황 출력
205
+ fn print_batch_progress(current: i32, total: i32, message: str) {
206
+ var percent = (current * 100) / total
207
+ println("[" + str(percent) + "%] " + message)
208
+ }
209
+
210
+ /// 배치 작업 결과 요약
211
+ fn print_batch_summary(result: BatchResult) {
212
+ println("✓ Batch operation completed")
213
+ println(" Total: " + str(result.total))
214
+ println(" Success: " + str(result.success))
215
+ println(" Failed: " + str(result.failed))
216
+
217
+ if result.failed > 0 {
218
+ println("\nErrors:")
219
+ var i: i32 = 0
220
+ while i < length(result.errors) && i < 10 {
221
+ println(" - " + result.errors[i])
222
+ i = i + 1
223
+ }
224
+
225
+ if length(result.errors) > 10 {
226
+ println(" ... and " + str(length(result.errors) - 10) + " more")
227
+ }
228
+ }
229
+ }
230
+
231
+ // ==================== 배치 처리 패턴 ====================
232
+
233
+ /// 저장소 배열에 대한 배치 생성
234
+ async fn batch_create_repos(
235
+ service: RepoService,
236
+ repos: [CreateRepoRequest],
237
+ parallel: i32
238
+ ) -> BatchResult {
239
+ var result = BatchResult {
240
+ total: length(repos),
241
+ success: 0,
242
+ failed: 0,
243
+ errors: []
244
+ }
245
+
246
+ // TODO: 병렬 실행 구현
247
+ // 현재: 순차 실행
248
+
249
+ var i: i32 = 0
250
+ while i < length(repos) {
251
+ var req = repos[i]
252
+ var repo_result = await create_repo(service, req)
253
+
254
+ match repo_result {
255
+ Result::Ok(_) => {
256
+ result.success = result.success + 1
257
+ }
258
+ Result::Err(err) => {
259
+ result.failed = result.failed + 1
260
+ result.errors.push(error_message(err))
261
+ }
262
+ }
263
+
264
+ print_batch_progress(i + 1, result.total, "Creating " + req.name)
265
+ i = i + 1
266
+ }
267
+
268
+ result
269
+ }
270
+
271
+ /// 저장소 배열에 대한 배치 삭제
272
+ async fn batch_delete_repos(
273
+ service: RepoService,
274
+ repo_paths: [str],
275
+ parallel: i32
276
+ ) -> BatchResult {
277
+ var result = BatchResult {
278
+ total: length(repo_paths),
279
+ success: 0,
280
+ failed: 0,
281
+ errors: []
282
+ }
283
+
284
+ // TODO: 병렬 실행 구현
285
+
286
+ var i: i32 = 0
287
+ while i < length(repo_paths) {
288
+ var path = repo_paths[i]
289
+ var parts = split_repo_path(path)
290
+
291
+ if length(parts) >= 2 {
292
+ var owner = parts[0]
293
+ var repo_name = parts[1]
294
+
295
+ var del_result = await delete_repo(service, owner, repo_name)
296
+
297
+ match del_result {
298
+ Result::Ok(_) => {
299
+ result.success = result.success + 1
300
+ }
301
+ Result::Err(err) => {
302
+ result.failed = result.failed + 1
303
+ result.errors.push(error_message(err))
304
+ }
305
+ }
306
+ }
307
+
308
+ print_batch_progress(i + 1, result.total, "Deleting " + path)
309
+ i = i + 1
310
+ }
311
+
312
+ result
313
+ }
314
+
315
+ // ==================== 유틸리티 ====================
316
+
317
+ fn split_repo_path(path: str) -> [str] {
318
+ var result: [str] = []
319
+ var idx = indexOf(path, "/")
320
+ if idx == -1 {
321
+ result.push(path)
322
+ return result
323
+ }
324
+ result.push(substring(path, 0, idx))
325
+ result.push(substring(path, idx + 1, length(path)))
326
+ result
327
+ }
328
+
329
+ fn indexOf(s: str, substr: str) -> i32 {
330
+ var i: i32 = 0
331
+ var len = length(s)
332
+ var sublen = length(substr)
333
+ while i <= len - sublen {
334
+ if substring(s, i, i + sublen) == substr { return i }
335
+ i = i + 1
336
+ }
337
+ -1
338
+ }
339
+
340
+ fn parse_int(s: str) -> i32 {
341
+ 0 // TODO: implement parse_int
342
+ }
343
+
344
+ // 필요한 함수들:
345
+ // - get_positional, has_flag, get_flag
346
+ // - get_default_host, new_client, new_cache
347
+ // - new_repo_service, create_repo, delete_repo, list_repos
348
+ // - read_file, parse_yaml
349
+ // - error_message
@@ -0,0 +1,199 @@
1
+ // FreeLang v4.2 — gogs-cli Phase 5 설정 명령어
2
+ // set, get 구현
3
+ // 150라인
4
+
5
+ /// 설정 저장
6
+ /// gogs config set KEY VALUE
7
+ async fn cmd_config_set(args: CliArgs) -> CliResult {
8
+ // 1. 인자 검증
9
+ var key = get_positional(args, 0)
10
+ var value = get_positional(args, 1)
11
+
12
+ if key == "" {
13
+ return CliResult {
14
+ exit_code: 1,
15
+ output: "",
16
+ error: "Key is required"
17
+ }
18
+ }
19
+
20
+ if value == "" {
21
+ return CliResult {
22
+ exit_code: 1,
23
+ output: "",
24
+ error: "Value is required"
25
+ }
26
+ }
27
+
28
+ // 2. 설정 로드
29
+ var cfg = await load_config()
30
+
31
+ // 3. 설정 값 저장 (확장 필드)
32
+ // TODO: Config 구조에 사용자 정의 필드 지원 필요
33
+ // cfg.settings[key] = value
34
+
35
+ // 4. 설정 저장
36
+ var saved = await save_config(cfg)
37
+
38
+ if saved {
39
+ CliResult {
40
+ exit_code: 0,
41
+ output: "✓ Configuration saved: " + key + " = " + value,
42
+ error: ""
43
+ }
44
+ } else {
45
+ CliResult {
46
+ exit_code: 1,
47
+ output: "",
48
+ error: "Failed to save configuration"
49
+ }
50
+ }
51
+ }
52
+
53
+ /// 설정 조회
54
+ /// gogs config get KEY
55
+ async fn cmd_config_get(args: CliArgs) -> CliResult {
56
+ // 1. 인자 검증
57
+ var key = get_positional(args, 0)
58
+
59
+ if key == "" {
60
+ return CliResult {
61
+ exit_code: 1,
62
+ output: "",
63
+ error: "Key is required"
64
+ }
65
+ }
66
+
67
+ // 2. 설정 로드
68
+ var cfg = await load_config()
69
+
70
+ // 3. 값 조회
71
+ // TODO: Config 구조에 사용자 정의 필드 지원 필요
72
+ // var value = cfg.settings[key]
73
+
74
+ var value = "" // placeholder
75
+
76
+ if value == "" {
77
+ return CliResult {
78
+ exit_code: 1,
79
+ output: "",
80
+ error: "Configuration key not found: " + key
81
+ }
82
+ }
83
+
84
+ CliResult {
85
+ exit_code: 0,
86
+ output: value,
87
+ error: ""
88
+ }
89
+ }
90
+
91
+ // ==================== 기본 설정 값 ====================
92
+
93
+ /// 기본 설정
94
+ struct ConfigSettings {
95
+ editor: str // 기본 에디터 (vim, nano, etc.)
96
+ output_format: str // 기본 출력 포맷 (text, json, yaml)
97
+ auto_confirm: bool // 자동 확인 (위험한 작업)
98
+ color_output: bool // 색상 출력
99
+ }
100
+
101
+ /// 기본 설정 값
102
+ fn default_settings() -> ConfigSettings {
103
+ ConfigSettings {
104
+ editor: "vim",
105
+ output_format: "text",
106
+ auto_confirm: false,
107
+ color_output: true
108
+ }
109
+ }
110
+
111
+ // ==================== 설정 관리 ====================
112
+
113
+ /// 설정 파일 존재 확인
114
+ async fn config_exists() -> bool {
115
+ // TODO: file system 확인 필요
116
+ false // placeholder
117
+ }
118
+
119
+ /// 기본 설정 파일 생성
120
+ async fn init_config() -> bool {
121
+ var cfg = Config {
122
+ default_host: "",
123
+ hosts: []
124
+ }
125
+
126
+ var saved = await save_config(cfg)
127
+ saved
128
+ }
129
+
130
+ /// 모든 설정 보기
131
+ async fn show_all_config() -> CliResult {
132
+ var cfg = await load_config()
133
+
134
+ var output = ""
135
+ output = output + "╔════════════════════════════════════════╗\n"
136
+ output = output + "║ Configuration ║\n"
137
+ output = output + "╚════════════════════════════════════════╝\n"
138
+ output = output + "\n"
139
+
140
+ output = output + "Default Host: " + cfg.default_host + "\n"
141
+ output = output + "Hosts: " + str(length(cfg.hosts)) + "\n"
142
+
143
+ var i: i32 = 0
144
+ while i < length(cfg.hosts) {
145
+ var host = cfg.hosts[i]
146
+ output = output + " - " + host.name + ": " + host.url + "\n"
147
+ i = i + 1
148
+ }
149
+
150
+ output = output + "\n"
151
+
152
+ CliResult {
153
+ exit_code: 0,
154
+ output: output,
155
+ error: ""
156
+ }
157
+ }
158
+
159
+ /// 설정 유효성 검증
160
+ fn validate_config(cfg: Config) -> bool {
161
+ if cfg.default_host == "" {
162
+ return false
163
+ }
164
+
165
+ var i: i32 = 0
166
+ while i < length(cfg.hosts) {
167
+ var host = cfg.hosts[i]
168
+ if host.name == "" || host.url == "" || host.token == "" {
169
+ return false
170
+ }
171
+ i = i + 1
172
+ }
173
+
174
+ true
175
+ }
176
+
177
+ // ==================== 환경 변수 지원 ====================
178
+
179
+ /// 환경 변수에서 설정 로드
180
+ fn load_from_env() -> Config {
181
+ // TODO: 환경 변수 읽기 구현
182
+ // GOGS_HOST, GOGS_TOKEN, GOGS_URL 등
183
+
184
+ Config {
185
+ default_host: "",
186
+ hosts: []
187
+ }
188
+ }
189
+
190
+ /// 환경 변수 확인
191
+ fn has_env_config() -> bool {
192
+ // TODO: 환경 변수 확인 구현
193
+ false
194
+ }
195
+
196
+ // 필요한 함수들:
197
+ // - get_positional
198
+ // - load_config, save_config
199
+ // - error_message