autosnippet 3.0.0 → 3.0.2
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.
- package/README.md +230 -324
- package/bin/api-server.js +1 -1
- package/bin/cli.js +204 -244
- package/bin/mcp-server.js +5 -3
- package/config/knowledge-base.config.js +132 -132
- package/dashboard/dist/assets/{icons-CEfgGaZi.js → icons-Cdq22n2i.js} +95 -100
- package/dashboard/dist/assets/index-ClkyPkDX.js +133 -0
- package/dashboard/dist/assets/index-t4QrJwv1.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/lib/bootstrap.js +8 -8
- package/lib/cli/AiScanService.js +86 -40
- package/lib/cli/KnowledgeSyncService.js +113 -74
- package/lib/cli/SetupService.js +439 -277
- package/lib/cli/UpgradeService.js +63 -100
- package/lib/core/AstAnalyzer.js +276 -597
- package/lib/core/ast/ProjectGraph.js +101 -40
- package/lib/core/ast/ensure-grammars.js +232 -0
- package/lib/core/ast/index.js +115 -0
- package/lib/core/ast/lang-dart.js +661 -0
- package/lib/core/ast/lang-go.js +530 -0
- package/lib/core/ast/lang-java.js +435 -0
- package/lib/core/ast/lang-javascript.js +272 -0
- package/lib/core/ast/lang-kotlin.js +423 -0
- package/lib/core/ast/lang-objc.js +388 -0
- package/lib/core/ast/lang-python.js +371 -0
- package/lib/core/ast/lang-swift.js +337 -0
- package/lib/core/ast/lang-typescript.js +503 -0
- package/lib/core/capability/CapabilityProbe.js +18 -9
- package/lib/core/constitution/Constitution.js +2 -3
- package/lib/core/constitution/ConstitutionValidator.js +65 -24
- package/lib/core/discovery/DartDiscoverer.js +534 -0
- package/lib/core/discovery/DiscovererRegistry.js +83 -0
- package/lib/core/discovery/GenericDiscoverer.js +225 -0
- package/lib/core/discovery/GoDiscoverer.js +541 -0
- package/lib/core/discovery/JvmDiscoverer.js +506 -0
- package/lib/core/discovery/NodeDiscoverer.js +466 -0
- package/lib/core/discovery/ProjectDiscoverer.js +93 -0
- package/lib/core/discovery/PythonDiscoverer.js +338 -0
- package/lib/core/discovery/SpmDiscoverer.js +5 -0
- package/lib/core/discovery/index.js +53 -0
- package/lib/core/enhancement/EnhancementPack.js +71 -0
- package/lib/core/enhancement/EnhancementRegistry.js +47 -0
- package/lib/core/enhancement/android-enhancement.js +102 -0
- package/lib/core/enhancement/django-enhancement.js +70 -0
- package/lib/core/enhancement/fastapi-enhancement.js +63 -0
- package/lib/core/enhancement/go-grpc-enhancement.js +152 -0
- package/lib/core/enhancement/go-web-enhancement.js +201 -0
- package/lib/core/enhancement/index.js +65 -0
- package/lib/core/enhancement/node-server-enhancement.js +88 -0
- package/lib/core/enhancement/react-enhancement.js +86 -0
- package/lib/core/enhancement/spring-enhancement.js +112 -0
- package/lib/core/enhancement/vue-enhancement.js +96 -0
- package/lib/core/gateway/Gateway.js +8 -9
- package/lib/core/gateway/GatewayActionRegistry.js +1 -1
- package/lib/core/permission/PermissionManager.js +12 -8
- package/lib/domain/index.js +13 -9
- package/lib/domain/knowledge/KnowledgeEntry.js +111 -101
- package/lib/domain/knowledge/KnowledgeRepository.js +0 -1
- package/lib/domain/knowledge/Lifecycle.js +22 -22
- package/lib/domain/knowledge/index.js +9 -12
- package/lib/domain/knowledge/values/Constraints.js +31 -21
- package/lib/domain/knowledge/values/Content.js +21 -13
- package/lib/domain/knowledge/values/Quality.js +31 -18
- package/lib/domain/knowledge/values/Reasoning.js +20 -12
- package/lib/domain/knowledge/values/Relations.js +37 -25
- package/lib/domain/knowledge/values/Stats.js +18 -12
- package/lib/domain/knowledge/values/index.js +4 -3
- package/lib/domain/snippet/Snippet.js +35 -10
- package/lib/external/ai/AiFactory.js +48 -16
- package/lib/external/ai/AiProvider.js +184 -90
- package/lib/external/ai/providers/ClaudeProvider.js +25 -12
- package/lib/external/ai/providers/GoogleGeminiProvider.js +59 -30
- package/lib/external/ai/providers/MockProvider.js +9 -3
- package/lib/external/ai/providers/OpenAiProvider.js +51 -29
- package/lib/external/mcp/McpServer.js +66 -36
- package/lib/external/mcp/errorHandler.js +23 -11
- package/lib/external/mcp/handlers/LanguageExtensions.js +138 -53
- package/lib/external/mcp/handlers/TargetClassifier.js +52 -16
- package/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +81 -20
- package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +71 -42
- package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +9 -17
- package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +14 -9
- package/lib/external/mcp/handlers/bootstrap/pipeline/dimension-context.js +15 -7
- package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +352 -153
- package/lib/external/mcp/handlers/bootstrap/pipeline/tier-scheduler.js +52 -12
- package/lib/external/mcp/handlers/bootstrap/skills.js +143 -39
- package/lib/external/mcp/handlers/bootstrap.js +691 -168
- package/lib/external/mcp/handlers/browse.js +66 -22
- package/lib/external/mcp/handlers/candidate.js +118 -35
- package/lib/external/mcp/handlers/consolidated.js +49 -17
- package/lib/external/mcp/handlers/guard.js +104 -39
- package/lib/external/mcp/handlers/knowledge.js +60 -36
- package/lib/external/mcp/handlers/search.js +43 -14
- package/lib/external/mcp/handlers/skill.js +120 -45
- package/lib/external/mcp/handlers/structure.js +240 -86
- package/lib/external/mcp/handlers/system.js +42 -12
- package/lib/external/mcp/handlers/wiki.js +58 -33
- package/lib/external/mcp/tools.js +306 -123
- package/lib/http/HttpServer.js +72 -47
- package/lib/http/middleware/RateLimiter.js +5 -3
- package/lib/http/middleware/errorHandler.js +6 -1
- package/lib/http/middleware/requestLogger.js +14 -3
- package/lib/http/middleware/roleResolver.js +30 -23
- package/lib/http/routes/ai.js +387 -265
- package/lib/http/routes/auth.js +81 -61
- package/lib/http/routes/candidates.js +430 -320
- package/lib/http/routes/commands.js +289 -189
- package/lib/http/routes/extract.js +158 -125
- package/lib/http/routes/guardRules.js +309 -217
- package/lib/http/routes/knowledge.js +213 -154
- package/lib/http/routes/modules.js +578 -0
- package/lib/http/routes/monitoring.js +6 -6
- package/lib/http/routes/recipes.js +104 -93
- package/lib/http/routes/search.js +361 -305
- package/lib/http/routes/skills.js +145 -98
- package/lib/http/routes/snippets.js +42 -30
- package/lib/http/routes/spm.js +3 -405
- package/lib/http/routes/violations.js +113 -93
- package/lib/http/routes/wiki.js +211 -170
- package/lib/http/utils/routeHelpers.js +3 -1
- package/lib/http/utils/sse-sessions.js +16 -6
- package/lib/http/utils/sse.js +15 -5
- package/lib/infrastructure/audit/AuditLogger.js +5 -2
- package/lib/infrastructure/audit/AuditStore.js +10 -7
- package/lib/infrastructure/cache/CacheService.js +3 -1
- package/lib/infrastructure/cache/GraphCache.js +8 -4
- package/lib/infrastructure/cache/UnifiedCacheAdapter.js +1 -1
- package/lib/infrastructure/config/ConfigLoader.js +9 -5
- package/lib/infrastructure/config/Defaults.js +30 -10
- package/lib/infrastructure/config/Paths.js +28 -8
- package/lib/infrastructure/config/TriggerSymbol.js +22 -10
- package/lib/infrastructure/database/DatabaseConnection.js +15 -10
- package/lib/infrastructure/database/migrations/001_initial_schema.js +0 -1
- package/lib/infrastructure/external/ClipboardManager.js +6 -2
- package/lib/infrastructure/external/NativeUi.js +50 -43
- package/lib/infrastructure/external/OpenBrowser.js +14 -17
- package/lib/infrastructure/external/XcodeAutomation.js +14 -258
- package/lib/infrastructure/logging/Logger.js +46 -30
- package/lib/infrastructure/monitoring/ErrorTracker.js +7 -5
- package/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -4
- package/lib/infrastructure/paths/HeaderResolver.js +25 -9
- package/lib/infrastructure/paths/PathFinder.js +34 -12
- package/lib/infrastructure/plugin/PluginManager.js +26 -8
- package/lib/infrastructure/realtime/RealtimeService.js +2 -2
- package/lib/infrastructure/vector/Chunker.js +22 -7
- package/lib/infrastructure/vector/IndexingPipeline.js +46 -22
- package/lib/infrastructure/vector/JsonVectorAdapter.js +90 -53
- package/lib/infrastructure/vector/VectorStore.js +28 -10
- package/lib/injection/ServiceContainer.js +247 -93
- package/lib/platform/ios/index.js +63 -0
- package/lib/platform/ios/routes/spm.js +437 -0
- package/lib/platform/ios/snippet/PlaceholderConverter.js +55 -0
- package/lib/platform/ios/snippet/XcodeCodec.js +112 -0
- package/lib/{service → platform/ios}/spm/DependencyGraph.js +41 -17
- package/lib/{service → platform/ios}/spm/PackageSwiftParser.js +41 -14
- package/lib/{service → platform/ios}/spm/PolicyEngine.js +9 -4
- package/lib/platform/ios/spm/SpmDiscoverer.js +122 -0
- package/lib/{service → platform/ios}/spm/SpmService.js +385 -127
- package/lib/{service/automation → platform/ios/xcode}/SaveEventFilter.js +8 -7
- package/lib/platform/ios/xcode/XcodeAutomation.js +350 -0
- package/lib/{service/automation → platform/ios/xcode}/XcodeIntegration.js +325 -145
- package/lib/repository/base/BaseRepository.js +7 -9
- package/lib/repository/knowledge/KnowledgeRepository.impl.js +98 -75
- package/lib/repository/token/TokenUsageStore.js +4 -2
- package/lib/service/automation/ActionPipeline.js +1 -1
- package/lib/service/automation/AutomationOrchestrator.js +8 -4
- package/lib/service/automation/ContextCollector.js +7 -5
- package/lib/service/automation/DirectiveDetector.js +23 -16
- package/lib/service/automation/FileWatcher.js +112 -56
- package/lib/service/automation/TriggerResolver.js +6 -4
- package/lib/service/automation/handlers/AlinkHandler.js +24 -12
- package/lib/service/automation/handlers/CreateHandler.js +19 -20
- package/lib/service/automation/handlers/DraftHandler.js +14 -8
- package/lib/service/automation/handlers/GuardHandler.js +93 -63
- package/lib/service/automation/handlers/HeaderHandler.js +1 -6
- package/lib/service/automation/handlers/SearchHandler.js +155 -88
- package/lib/service/bootstrap/BootstrapTaskManager.js +77 -35
- package/lib/service/candidate/SimilarityService.js +25 -9
- package/lib/service/chat/AnalystAgent.js +50 -24
- package/lib/service/chat/CandidateGuardrail.js +143 -17
- package/lib/service/chat/ChatAgent.js +759 -243
- package/lib/service/chat/ContextWindow.js +116 -71
- package/lib/service/chat/ConversationStore.js +77 -36
- package/lib/service/chat/EpisodicConsolidator.js +47 -23
- package/lib/service/chat/HandoffProtocol.js +98 -22
- package/lib/service/chat/Memory.js +34 -14
- package/lib/service/chat/ProducerAgent.js +40 -20
- package/lib/service/chat/ProjectSemanticMemory.js +109 -78
- package/lib/service/chat/ReasoningLayer.js +148 -70
- package/lib/service/chat/ReasoningTrace.js +44 -32
- package/lib/service/chat/TaskPipeline.js +39 -19
- package/lib/service/chat/ToolRegistry.js +48 -29
- package/lib/service/chat/WorkingMemory.js +44 -18
- package/lib/service/chat/tools.js +1096 -494
- package/lib/service/context/RecipeExtractor.js +132 -51
- package/lib/service/cursor/CursorDeliveryPipeline.js +82 -37
- package/lib/service/cursor/KnowledgeCompressor.js +25 -22
- package/lib/service/cursor/RulesGenerator.js +13 -7
- package/lib/service/cursor/SkillsSyncer.js +77 -27
- package/lib/service/cursor/TokenBudget.js +2 -2
- package/lib/service/cursor/TopicClassifier.js +54 -20
- package/lib/service/guard/ComplianceReporter.js +55 -43
- package/lib/service/guard/ExclusionManager.js +67 -29
- package/lib/service/guard/GuardCheckEngine.js +381 -86
- package/lib/service/guard/GuardFeedbackLoop.js +22 -10
- package/lib/service/guard/GuardService.js +29 -19
- package/lib/service/guard/RuleLearner.js +55 -23
- package/lib/service/guard/SourceFileCollector.js +27 -20
- package/lib/service/guard/ViolationsStore.js +43 -38
- package/lib/service/knowledge/CodeEntityGraph.js +147 -82
- package/lib/service/knowledge/ConfidenceRouter.js +12 -10
- package/lib/service/knowledge/KnowledgeFileWriter.js +147 -56
- package/lib/service/knowledge/KnowledgeGraphService.js +81 -34
- package/lib/service/knowledge/KnowledgeService.js +222 -112
- package/lib/service/module/ModuleService.js +969 -0
- package/lib/service/quality/FeedbackCollector.js +27 -15
- package/lib/service/quality/QualityScorer.js +78 -24
- package/lib/service/recipe/RecipeCandidateValidator.js +110 -44
- package/lib/service/recipe/RecipeParser.js +78 -45
- package/lib/service/search/CoarseRanker.js +43 -28
- package/lib/service/search/CrossEncoderReranker.js +32 -21
- package/lib/service/search/InvertedIndex.js +21 -7
- package/lib/service/search/MultiSignalRanker.js +90 -28
- package/lib/service/search/RetrievalFunnel.js +45 -24
- package/lib/service/search/SearchEngine.js +255 -103
- package/lib/service/skills/EventAggregator.js +32 -15
- package/lib/service/skills/SignalCollector.js +140 -64
- package/lib/service/skills/SkillAdvisor.js +79 -42
- package/lib/service/skills/SkillHooks.js +16 -14
- package/lib/service/snippet/PlaceholderConverter.js +5 -0
- package/lib/service/snippet/SnippetFactory.js +116 -99
- package/lib/service/snippet/SnippetInstaller.js +234 -62
- package/lib/service/snippet/codecs/SnippetCodec.js +67 -0
- package/lib/service/snippet/codecs/VSCodeCodec.js +102 -0
- package/lib/service/snippet/codecs/XcodeCodec.js +5 -0
- package/lib/service/wiki/WikiGenerator.js +637 -263
- package/lib/shared/DimensionCopyRegistry.js +472 -0
- package/lib/shared/LanguageService.js +399 -0
- package/lib/shared/PathGuard.js +45 -28
- package/lib/shared/RecipeReadinessChecker.js +72 -12
- package/lib/shared/constants.js +41 -41
- package/lib/shared/errors/BaseError.js +2 -2
- package/lib/shared/errors/index.js +4 -4
- package/lib/shared/similarity.js +25 -8
- package/lib/shared/token-utils.js +6 -2
- package/lib/shared/utils/common.js +12 -4
- package/package.json +49 -13
- package/scripts/bench-real-projects.mjs +256 -0
- package/scripts/build-native-ui.js +30 -30
- package/scripts/clear-old-vector-index.js +5 -35
- package/scripts/clear-vector-cache.js +7 -37
- package/scripts/collect-test-project-stats.mjs +160 -0
- package/scripts/diagnose-mcp.js +41 -32
- package/scripts/ensure-parse-package.js +6 -9
- package/scripts/generate-recipe-drafts.js +116 -77
- package/scripts/init-db.js +3 -20
- package/scripts/init-snippets.js +305 -0
- package/scripts/init-vector-db.js +173 -170
- package/scripts/install-cursor-skill.js +148 -104
- package/scripts/install-full.js +8 -21
- package/scripts/install-vscode-copilot.js +146 -145
- package/scripts/migrate-md-to-knowledge.mjs +139 -151
- package/scripts/postinstall-safe.js +5 -17
- package/scripts/recipe-audit.js +106 -82
- package/scripts/release.js +283 -323
- package/scripts/setup-mcp-config.js +60 -52
- package/scripts/verify-context-api.js +20 -20
- package/skills/autosnippet-analysis/SKILL.md +10 -6
- package/skills/autosnippet-candidates/SKILL.md +27 -26
- package/skills/autosnippet-coldstart/SKILL.md +555 -38
- package/skills/autosnippet-concepts/SKILL.md +349 -337
- package/skills/autosnippet-create/SKILL.md +5 -5
- package/skills/autosnippet-reference-dart/SKILL.md +543 -0
- package/skills/autosnippet-reference-go/SKILL.md +539 -0
- package/skills/autosnippet-reference-java/SKILL.md +534 -0
- package/skills/autosnippet-reference-jsts/SKILL.md +41 -9
- package/skills/autosnippet-reference-kotlin/SKILL.md +526 -0
- package/skills/autosnippet-reference-objc/SKILL.md +29 -6
- package/skills/autosnippet-reference-python/SKILL.md +800 -0
- package/skills/autosnippet-reference-swift/SKILL.md +70 -14
- package/skills/autosnippet-structure/SKILL.md +4 -4
- package/templates/cursor-rules/autosnippet-conventions.mdc +2 -2
- package/templates/recipes-setup/README.md +2 -2
- package/templates/recipes-setup/_template.md +1 -1
- package/dashboard/dist/assets/index-Bun3ld_J.css +0 -1
- package/dashboard/dist/assets/index-_Sk_Dmg3.js +0 -143
- package/resources/asd-entry/main.swift +0 -159
- package/scripts/build-asd-entry.js +0 -51
- package/scripts/init-xcode-snippets.js +0 -311
- package/template.json +0 -39
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env swift
|
|
2
|
-
/*
|
|
3
|
-
* AutoSnippet 完整性校验入口(Swift,仅 macOS)
|
|
4
|
-
* 读 checksums.json,校验关键文件 SHA-256,通过则设置 ASD_VERIFIED=1 并 spawn node bin/asd-cli.js。
|
|
5
|
-
* 收到 SIGINT/SIGTERM 时转发给子进程,避免 asd ui 按 Ctrl+C 后 Node 成为孤儿进程占用 3000 端口。
|
|
6
|
-
* 构建:node scripts/build-asd-entry.js,产物 bin/asd-verify。
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import Foundation
|
|
10
|
-
import CryptoKit
|
|
11
|
-
import Dispatch
|
|
12
|
-
|
|
13
|
-
func fail(_ msg: String) -> Never {
|
|
14
|
-
fputs(msg + "\n", stderr)
|
|
15
|
-
exit(1)
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/// 从可执行路径解析包根目录(bin/asd-verify 的上级的上级)
|
|
19
|
-
func getPackageRoot() -> String? {
|
|
20
|
-
let argv0 = CommandLine.arguments[0]
|
|
21
|
-
let path = (argv0 as NSString).standardizingPath
|
|
22
|
-
var url = URL(fileURLWithPath: path)
|
|
23
|
-
if path != (path as NSString).resolvingSymlinksInPath {
|
|
24
|
-
url = URL(fileURLWithPath: (path as NSString).resolvingSymlinksInPath)
|
|
25
|
-
}
|
|
26
|
-
var dir = url.deletingLastPathComponent().path // bin
|
|
27
|
-
dir = (dir as NSString).deletingLastPathComponent // package root
|
|
28
|
-
return dir
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/// 文件内容 SHA-256 小写 hex
|
|
32
|
-
func sha256Hex(filePath: String) -> String? {
|
|
33
|
-
guard let data = try? Data(contentsOf: URL(fileURLWithPath: filePath)) else { return nil }
|
|
34
|
-
let hash = SHA256.hash(data: data)
|
|
35
|
-
return hash.map { String(format: "%02x", $0) }.joined()
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/// 校验 checksums.json 中列出的文件。拒绝 relPath 含 ".." 或为绝对路径。
|
|
39
|
-
/// 根据环境变量决定是否打印详细信息(开发者模式)。
|
|
40
|
-
func verifyIntegrity(root: String, checksumsPath: String, debugMode: Bool) -> Bool {
|
|
41
|
-
guard let data = try? Data(contentsOf: URL(fileURLWithPath: checksumsPath)) else {
|
|
42
|
-
if debugMode {
|
|
43
|
-
fputs("asd: 无法读取 checksums.json\n", stderr)
|
|
44
|
-
}
|
|
45
|
-
return false
|
|
46
|
-
}
|
|
47
|
-
guard let json = try? JSONSerialization.jsonObject(with: data),
|
|
48
|
-
let entries = json as? [String: String] else {
|
|
49
|
-
if debugMode {
|
|
50
|
-
fputs("asd: checksums.json 格式无效\n", stderr)
|
|
51
|
-
}
|
|
52
|
-
return false
|
|
53
|
-
}
|
|
54
|
-
let rootNorm = (root as NSString).standardizingPath
|
|
55
|
-
for (relPath, expectedHex) in entries {
|
|
56
|
-
if relPath.hasPrefix("/") || relPath.contains("..") {
|
|
57
|
-
if debugMode {
|
|
58
|
-
fputs("asd: 校验拒绝非法路径: \(relPath)\n", stderr)
|
|
59
|
-
}
|
|
60
|
-
return false
|
|
61
|
-
}
|
|
62
|
-
let fullPath = (root as NSString).appendingPathComponent(relPath)
|
|
63
|
-
let fullNorm = (fullPath as NSString).standardizingPath
|
|
64
|
-
let rootSlash = rootNorm.hasSuffix("/") ? rootNorm : rootNorm + "/"
|
|
65
|
-
guard fullNorm == rootNorm || fullNorm.hasPrefix(rootSlash) else {
|
|
66
|
-
if debugMode {
|
|
67
|
-
fputs("asd: 校验拒绝路径逃逸: \(relPath)\n", stderr)
|
|
68
|
-
}
|
|
69
|
-
return false
|
|
70
|
-
}
|
|
71
|
-
guard let actualHex = sha256Hex(filePath: fullPath) else {
|
|
72
|
-
if debugMode {
|
|
73
|
-
fputs("asd: 完整性校验失败: \(relPath)\n", stderr)
|
|
74
|
-
} else {
|
|
75
|
-
fputs("asd: 完整性校验失败\n", stderr)
|
|
76
|
-
}
|
|
77
|
-
return false
|
|
78
|
-
}
|
|
79
|
-
if actualHex.lowercased() != expectedHex.lowercased() {
|
|
80
|
-
if debugMode {
|
|
81
|
-
fputs("asd: 完整性校验失败: \(relPath)\n", stderr)
|
|
82
|
-
} else {
|
|
83
|
-
fputs("asd: 完整性校验失败\n", stderr)
|
|
84
|
-
}
|
|
85
|
-
return false
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return true
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/// 执行 node bin/asd-cli.js [args...],将调用时的 cwd 传入 ASD_CWD,校验通过则设 ASD_VERIFIED=1。
|
|
92
|
-
/// 收到 SIGINT/SIGTERM 时转发给子进程,避免 asd ui 按 Ctrl+C 后 Node 未退出导致 3000 端口被占用。
|
|
93
|
-
func spawnNode(root: String, integrityVerified: Bool) -> Int32 {
|
|
94
|
-
let asnipPath = (root as NSString).appendingPathComponent("bin/asd-cli.js")
|
|
95
|
-
guard FileManager.default.fileExists(atPath: asnipPath) else {
|
|
96
|
-
fail("asd: 未找到 bin/asd-cli.js")
|
|
97
|
-
}
|
|
98
|
-
let nodeArgs = ["node", asnipPath] + Array(CommandLine.arguments.dropFirst())
|
|
99
|
-
let process = Process()
|
|
100
|
-
process.executableURL = URL(fileURLWithPath: "/usr/bin/env")
|
|
101
|
-
process.arguments = nodeArgs
|
|
102
|
-
process.currentDirectoryURL = URL(fileURLWithPath: root)
|
|
103
|
-
var env = ProcessInfo.processInfo.environment
|
|
104
|
-
env["ASD_CWD"] = FileManager.default.currentDirectoryPath
|
|
105
|
-
if integrityVerified {
|
|
106
|
-
env["ASD_VERIFIED"] = "1"
|
|
107
|
-
}
|
|
108
|
-
process.environment = env
|
|
109
|
-
process.standardInput = FileHandle.standardInput
|
|
110
|
-
process.standardOutput = FileHandle.standardOutput
|
|
111
|
-
process.standardError = FileHandle.standardError
|
|
112
|
-
do {
|
|
113
|
-
try process.run()
|
|
114
|
-
// 转发 SIGINT/SIGTERM 给子进程,避免 Ctrl+C 后仅 asd-verify 退出、Node 成为孤儿占用端口
|
|
115
|
-
signal(SIGINT, SIG_IGN)
|
|
116
|
-
signal(SIGTERM, SIG_IGN)
|
|
117
|
-
let queue = DispatchQueue.main
|
|
118
|
-
let sigintSource = DispatchSource.makeSignalSource(signal: SIGINT, queue: queue)
|
|
119
|
-
let sigtermSource = DispatchSource.makeSignalSource(signal: SIGTERM, queue: queue)
|
|
120
|
-
sigintSource.setEventHandler { process.terminate() }
|
|
121
|
-
sigtermSource.setEventHandler { process.terminate() }
|
|
122
|
-
sigintSource.resume()
|
|
123
|
-
sigtermSource.resume()
|
|
124
|
-
process.waitUntilExit()
|
|
125
|
-
return process.terminationStatus
|
|
126
|
-
} catch {
|
|
127
|
-
fail("asd: 启动 node 失败: \(error.localizedDescription)")
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// MARK: - Main
|
|
132
|
-
// 使用环境变量 ASD_SKIP_CHECKSUMS=1 或 ASD_SKIP_ENTRY_CHECK=1 可跳过完整性校验(仅限开发者模式)
|
|
133
|
-
// 使用环境变量 ASD_DEBUG=1 可打印详细校验信息
|
|
134
|
-
|
|
135
|
-
let skipChecksums = ProcessInfo.processInfo.environment["ASD_SKIP_CHECKSUMS"] == "1" ||
|
|
136
|
-
ProcessInfo.processInfo.environment["ASD_SKIP_ENTRY_CHECK"] == "1"
|
|
137
|
-
let debugMode = ProcessInfo.processInfo.environment["ASD_DEBUG"] == "1"
|
|
138
|
-
|
|
139
|
-
guard let root = getPackageRoot() else {
|
|
140
|
-
fail("asd: 无法解析包根目录")
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
let checksumsPath = (root as NSString).appendingPathComponent("checksums.json")
|
|
144
|
-
var integrityVerified = false
|
|
145
|
-
|
|
146
|
-
// 如果开发者模式跳过校验,直接启动 Node
|
|
147
|
-
if skipChecksums {
|
|
148
|
-
if debugMode {
|
|
149
|
-
fputs("asd: 开发者模式,跳过完整性校验\n", stderr)
|
|
150
|
-
}
|
|
151
|
-
integrityVerified = false
|
|
152
|
-
} else if FileManager.default.fileExists(atPath: checksumsPath) {
|
|
153
|
-
if !verifyIntegrity(root: root, checksumsPath: checksumsPath, debugMode: debugMode) {
|
|
154
|
-
exit(1)
|
|
155
|
-
}
|
|
156
|
-
integrityVerified = true
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
exit(spawnNode(root: root, integrityVerified: integrityVerified))
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 构建 asd 完整性校验入口(Swift,仅 macOS)。产物:bin/asd-verify。
|
|
5
|
-
* 若不存在或构建失败,将直接使用 node bin/cli.js。
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { fileURLToPath } from 'node:url';
|
|
9
|
-
import { dirname } from 'node:path';
|
|
10
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
const __dirname = dirname(__filename);
|
|
12
|
-
|
|
13
|
-
import { execSync } from 'node:child_process';
|
|
14
|
-
import path from 'node:path';
|
|
15
|
-
import fs from 'node:fs';
|
|
16
|
-
|
|
17
|
-
if (process.platform !== 'darwin') process.exit(0);
|
|
18
|
-
|
|
19
|
-
const root = path.resolve(__dirname, '..');
|
|
20
|
-
const src = path.join(root, 'resources', 'asd-entry', 'main.swift');
|
|
21
|
-
const out = path.join(root, 'bin', 'asd-verify');
|
|
22
|
-
|
|
23
|
-
// 检查是否在发布流程中
|
|
24
|
-
const isPublishing = process.env.npm_lifecycle_event === 'prepublishOnly';
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
fs.mkdirSync(path.join(root, 'bin'), { recursive: true });
|
|
28
|
-
execSync(`swiftc "${src}" -o "${out}"`, { cwd: root, stdio: 'pipe' });
|
|
29
|
-
|
|
30
|
-
// 验证构建结果
|
|
31
|
-
if (fs.existsSync(out)) {
|
|
32
|
-
console.log('✅ ASD Entry 构建成功');
|
|
33
|
-
}
|
|
34
|
-
} catch (err) {
|
|
35
|
-
// 如果在发布流程中构建失败,应该报错
|
|
36
|
-
if (isPublishing) {
|
|
37
|
-
console.error('❌ ASD Entry 构建失败(发布流程中)');
|
|
38
|
-
console.error('请确保:');
|
|
39
|
-
console.error(' 1. 当前系统是 macOS');
|
|
40
|
-
console.error(' 2. 已安装 Xcode Command Line Tools: xcode-select --install');
|
|
41
|
-
console.error(' 3. Swift 编译器可用: which swiftc');
|
|
42
|
-
process.exit(1);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// 在用户安装时,如果已有预编译的二进制文件,静默跳过
|
|
46
|
-
if (fs.existsSync(out)) {
|
|
47
|
-
console.log('ℹ️ 使用预编译的 ASD Entry');
|
|
48
|
-
} else {
|
|
49
|
-
console.log('⚠️ ASD Entry 未构建(将使用 Node.js 入口)');
|
|
50
|
-
}
|
|
51
|
-
}
|
|
@@ -1,311 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Xcode Snippet 初始化脚本
|
|
5
|
-
* 自动为 AutoSnippet 添加快速输入 Snippets 到 Xcode
|
|
6
|
-
*
|
|
7
|
-
* 用法:
|
|
8
|
-
* node scripts/init-xcode-snippets.js
|
|
9
|
-
* npm run init-snippets
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { execSync } from 'node:child_process';
|
|
13
|
-
import fs from 'node:fs';
|
|
14
|
-
import path from 'node:path';
|
|
15
|
-
import os from 'node:os';
|
|
16
|
-
|
|
17
|
-
class XcodeSnippetInitializer {
|
|
18
|
-
constructor() {
|
|
19
|
-
this.snippetsDir = path.join(
|
|
20
|
-
os.homedir(),
|
|
21
|
-
'Library/Developer/Xcode/UserData/CodeSnippets'
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
this.snippets = [
|
|
25
|
-
{
|
|
26
|
-
id: 'com.autosnippet.search.long',
|
|
27
|
-
shortcut: 'ass',
|
|
28
|
-
title: 'AutoSnippet: Search (Long)',
|
|
29
|
-
summary: 'Search and insert Recipe/Snippet from knowledge base',
|
|
30
|
-
content: '// as:search <#keyword#>',
|
|
31
|
-
scopes: ['All']
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
id: 'com.autosnippet.create',
|
|
35
|
-
shortcut: 'asc',
|
|
36
|
-
title: 'AutoSnippet: Create Recipe',
|
|
37
|
-
summary: 'Create new Recipe (Dashboard or clipboard/file)',
|
|
38
|
-
content: '// as:create <#-c or -f#>',
|
|
39
|
-
scopes: ['All']
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
id: 'com.autosnippet.audit',
|
|
43
|
-
shortcut: 'asa',
|
|
44
|
-
title: 'AutoSnippet: Audit Code',
|
|
45
|
-
summary: 'AI code review against knowledge base',
|
|
46
|
-
content: '// as:audit <#keyword or scope (file/target/project)#>',
|
|
47
|
-
scopes: ['All']
|
|
48
|
-
}
|
|
49
|
-
];
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* 生成 plist 格式的 Snippet 文件内容
|
|
54
|
-
*/
|
|
55
|
-
generateSnippetPlist(snippet) {
|
|
56
|
-
const escapedContent = snippet.content
|
|
57
|
-
.replace(/&/g, '&')
|
|
58
|
-
.replace(/</g, '<')
|
|
59
|
-
.replace(/>/g, '>')
|
|
60
|
-
.replace(/"/g, '"')
|
|
61
|
-
.replace(/'/g, ''');
|
|
62
|
-
|
|
63
|
-
const scopesXml = snippet.scopes
|
|
64
|
-
.map(scope => ` <string>${scope}</string>`)
|
|
65
|
-
.join('\n');
|
|
66
|
-
|
|
67
|
-
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
68
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
69
|
-
<plist version="1.0">
|
|
70
|
-
<dict>
|
|
71
|
-
<key>IDECodeSnippetCompletionPrefix</key>
|
|
72
|
-
<string>${snippet.shortcut}</string>
|
|
73
|
-
<key>IDECodeSnippetCompletionScopes</key>
|
|
74
|
-
<array>
|
|
75
|
-
${scopesXml}
|
|
76
|
-
</array>
|
|
77
|
-
<key>IDECodeSnippetContents</key>
|
|
78
|
-
<string>${escapedContent}</string>
|
|
79
|
-
<key>IDECodeSnippetIdentifier</key>
|
|
80
|
-
<string>${snippet.id}</string>
|
|
81
|
-
<key>IDECodeSnippetLanguage</key>
|
|
82
|
-
<string>Xcode.SourceCodeLanguage.Generic</string>
|
|
83
|
-
<key>IDECodeSnippetRelatedIdentifiers</key>
|
|
84
|
-
<array/>
|
|
85
|
-
<key>IDECodeSnippetSummary</key>
|
|
86
|
-
<string>${snippet.summary}</string>
|
|
87
|
-
<key>IDECodeSnippetTitle</key>
|
|
88
|
-
<string>${snippet.title}</string>
|
|
89
|
-
<key>IDECodeSnippetUserSnippet</key>
|
|
90
|
-
<true/>
|
|
91
|
-
<key>IDECodeSnippetVersion</key>
|
|
92
|
-
<integer>2</integer>
|
|
93
|
-
</dict>
|
|
94
|
-
</plist>`;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
* 创建或更新 Snippet 文件
|
|
99
|
-
*/
|
|
100
|
-
createSnippet(snippet) {
|
|
101
|
-
try {
|
|
102
|
-
const filename = `${snippet.id}.codesnippet`;
|
|
103
|
-
const filePath = path.join(this.snippetsDir, filename);
|
|
104
|
-
const content = this.generateSnippetPlist(snippet);
|
|
105
|
-
|
|
106
|
-
fs.writeFileSync(filePath, content, 'utf8');
|
|
107
|
-
console.log(` ✅ ${snippet.title}`);
|
|
108
|
-
console.log(` 快捷键: ${snippet.shortcut}`);
|
|
109
|
-
console.log(` 内容: ${snippet.content}`);
|
|
110
|
-
return true;
|
|
111
|
-
} catch (err) {
|
|
112
|
-
console.warn(` ❌ ${snippet.title}: ${err.message}`);
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
* 检查 Snippets 目录是否存在
|
|
119
|
-
*/
|
|
120
|
-
ensureSnippetsDir() {
|
|
121
|
-
if (!fs.existsSync(this.snippetsDir)) {
|
|
122
|
-
try {
|
|
123
|
-
fs.mkdirSync(this.snippetsDir, { recursive: true });
|
|
124
|
-
console.log(`✅ 创建 Snippets 目录: ${this.snippetsDir}`);
|
|
125
|
-
return true;
|
|
126
|
-
} catch (err) {
|
|
127
|
-
console.error(`❌ 无法创建 Snippets 目录: ${err.message}`);
|
|
128
|
-
return false;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
return true;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* 检查 Xcode 是否已安装
|
|
136
|
-
*/
|
|
137
|
-
checkXcodeInstalled() {
|
|
138
|
-
try {
|
|
139
|
-
execSync('xcode-select -p', { stdio: 'ignore' });
|
|
140
|
-
return true;
|
|
141
|
-
} catch (_) {
|
|
142
|
-
return false;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/**
|
|
147
|
-
* 初始化所有 Snippets
|
|
148
|
-
*/
|
|
149
|
-
async initialize() {
|
|
150
|
-
console.log('\n🚀 AutoSnippet Xcode Snippets 初始化\n');
|
|
151
|
-
|
|
152
|
-
// 检查平台
|
|
153
|
-
if (process.platform !== 'darwin') {
|
|
154
|
-
console.log('⚠️ 此脚本仅支持 macOS');
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
// 检查 Xcode
|
|
159
|
-
if (!this.checkXcodeInstalled()) {
|
|
160
|
-
console.log('⚠️ 未检测到 Xcode,Snippets 可能无法正常工作');
|
|
161
|
-
console.log(' 请确保已安装 Xcode 或运行: xcode-select --install\n');
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// 创建目录
|
|
165
|
-
if (!this.ensureSnippetsDir()) {
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// 创建 Snippets
|
|
170
|
-
console.log('\n📝 创建 Snippets:\n');
|
|
171
|
-
let successCount = 0;
|
|
172
|
-
for (const snippet of this.snippets) {
|
|
173
|
-
if (this.createSnippet(snippet)) {
|
|
174
|
-
successCount++;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// 总结
|
|
179
|
-
console.log(`\n${successCount}/${this.snippets.length} 个 Snippets 已创建\n`);
|
|
180
|
-
|
|
181
|
-
if (successCount === this.snippets.length) {
|
|
182
|
-
console.log('✅ 所有 Snippets 已成功添加到 Xcode!\n');
|
|
183
|
-
console.log('📌 快速开始:');
|
|
184
|
-
console.log(' 1. 在 Xcode 中打开任何源代码文件');
|
|
185
|
-
console.log(' 2. 输入 "ass" 并按 Tab 自动完成');
|
|
186
|
-
console.log(' 3. 在提示中输入关键词并保存');
|
|
187
|
-
console.log(' 4. AutoSnippet watch 会自动处理\n');
|
|
188
|
-
console.log('📚 可用快捷键:');
|
|
189
|
-
this.snippets.forEach(s => {
|
|
190
|
-
console.log(` • ${s.shortcut.padEnd(6)} → ${s.title}`);
|
|
191
|
-
});
|
|
192
|
-
console.log();
|
|
193
|
-
return true;
|
|
194
|
-
} else {
|
|
195
|
-
console.log('⚠️ 部分 Snippets 创建失败,请检查权限');
|
|
196
|
-
return false;
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* 列出已安装的 Snippets
|
|
202
|
-
*/
|
|
203
|
-
listSnippets() {
|
|
204
|
-
console.log('\n📋 AutoSnippet Snippets 清单\n');
|
|
205
|
-
|
|
206
|
-
if (!fs.existsSync(this.snippetsDir)) {
|
|
207
|
-
console.log('未找到 Snippets 目录');
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
const files = fs.readdirSync(this.snippetsDir);
|
|
212
|
-
const autoSnippets = files.filter(f => f.startsWith('com.autosnippet'));
|
|
213
|
-
|
|
214
|
-
if (autoSnippets.length === 0) {
|
|
215
|
-
console.log('未安装任何 AutoSnippet Snippets');
|
|
216
|
-
} else {
|
|
217
|
-
autoSnippets.forEach(file => {
|
|
218
|
-
const filePath = path.join(this.snippetsDir, file);
|
|
219
|
-
const stat = fs.statSync(filePath);
|
|
220
|
-
console.log(` ✓ ${file}`);
|
|
221
|
-
console.log(` 大小: ${(stat.size / 1024).toFixed(2)} KB`);
|
|
222
|
-
console.log(` 更新: ${stat.mtime.toLocaleString('zh-CN')}`);
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
console.log();
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* 移除所有 AutoSnippet Snippets
|
|
230
|
-
*/
|
|
231
|
-
removeSnippets() {
|
|
232
|
-
console.log('\n🗑️ 移除 AutoSnippet Snippets\n');
|
|
233
|
-
|
|
234
|
-
if (!fs.existsSync(this.snippetsDir)) {
|
|
235
|
-
console.log('未找到 Snippets 目录');
|
|
236
|
-
return;
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
const files = fs.readdirSync(this.snippetsDir);
|
|
240
|
-
const autoSnippets = files.filter(f => f.startsWith('com.autosnippet'));
|
|
241
|
-
|
|
242
|
-
let removedCount = 0;
|
|
243
|
-
autoSnippets.forEach(file => {
|
|
244
|
-
try {
|
|
245
|
-
const filePath = path.join(this.snippetsDir, file);
|
|
246
|
-
fs.unlinkSync(filePath);
|
|
247
|
-
console.log(` ✓ 已移除: ${file}`);
|
|
248
|
-
removedCount++;
|
|
249
|
-
} catch (err) {
|
|
250
|
-
console.warn(` ✗ 移除失败: ${file}`);
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
|
|
254
|
-
console.log(`\n已移除 ${removedCount} 个 Snippets\n`);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// 命令行接口
|
|
259
|
-
async function main() {
|
|
260
|
-
const command = process.argv[2] || 'init';
|
|
261
|
-
const initializer = new XcodeSnippetInitializer();
|
|
262
|
-
|
|
263
|
-
switch (command) {
|
|
264
|
-
case 'init':
|
|
265
|
-
await initializer.initialize();
|
|
266
|
-
break;
|
|
267
|
-
case 'list':
|
|
268
|
-
initializer.listSnippets();
|
|
269
|
-
break;
|
|
270
|
-
case 'remove':
|
|
271
|
-
initializer.removeSnippets();
|
|
272
|
-
break;
|
|
273
|
-
case 'help':
|
|
274
|
-
console.log(`
|
|
275
|
-
用法: node scripts/init-xcode-snippets.js [命令]
|
|
276
|
-
|
|
277
|
-
命令:
|
|
278
|
-
init 初始化 AutoSnippet Snippets(默认)
|
|
279
|
-
list 列出已安装的 Snippets
|
|
280
|
-
remove 移除所有 AutoSnippet Snippets
|
|
281
|
-
help 显示此帮助信息
|
|
282
|
-
|
|
283
|
-
示例:
|
|
284
|
-
node scripts/init-xcode-snippets.js init
|
|
285
|
-
node scripts/init-xcode-snippets.js list
|
|
286
|
-
`);
|
|
287
|
-
break;
|
|
288
|
-
default:
|
|
289
|
-
console.log(`未知命令: ${command}`);
|
|
290
|
-
console.log('使用 "help" 查看可用命令');
|
|
291
|
-
process.exit(1);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// 导出供其他脚本使用
|
|
296
|
-
export default {
|
|
297
|
-
XcodeSnippetInitializer,
|
|
298
|
-
initialize: async () => {
|
|
299
|
-
const initializer = new XcodeSnippetInitializer();
|
|
300
|
-
return initializer.initialize();
|
|
301
|
-
}
|
|
302
|
-
};
|
|
303
|
-
|
|
304
|
-
// 如果直接执行此文件
|
|
305
|
-
const isMain = process.argv[1] && import.meta.url === `file://${process.argv[1]}`;
|
|
306
|
-
if (isMain) {
|
|
307
|
-
main().catch(err => {
|
|
308
|
-
console.error('❌ 初始化失败:', err.message);
|
|
309
|
-
process.exit(1);
|
|
310
|
-
});
|
|
311
|
-
}
|
package/template.json
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"list": [
|
|
3
|
-
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
|
4
|
-
"<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n",
|
|
5
|
-
"<plist version=\"1.0\">\n",
|
|
6
|
-
"<dict>\n",
|
|
7
|
-
|
|
8
|
-
"\t<key>IDECodeSnippetCompletionPrefix</key>\n",
|
|
9
|
-
"{completion}",
|
|
10
|
-
|
|
11
|
-
"\t<key>IDECodeSnippetCompletionScopes</key>\n",
|
|
12
|
-
"\t<array>\n",
|
|
13
|
-
"\t\t<string>All</string>\n",
|
|
14
|
-
"\t</array>\n",
|
|
15
|
-
|
|
16
|
-
"\t<key>IDECodeSnippetContents</key>\n",
|
|
17
|
-
"{content}",
|
|
18
|
-
|
|
19
|
-
"\t<key>IDECodeSnippetIdentifier</key>\n",
|
|
20
|
-
"{identifier}",
|
|
21
|
-
|
|
22
|
-
"\t<key>IDECodeSnippetLanguage</key>\n",
|
|
23
|
-
"{language}",
|
|
24
|
-
|
|
25
|
-
"\t<key>IDECodeSnippetSummary</key>\n",
|
|
26
|
-
"{summary}",
|
|
27
|
-
|
|
28
|
-
"\t<key>IDECodeSnippetTitle</key>\n",
|
|
29
|
-
"{title}",
|
|
30
|
-
|
|
31
|
-
"\t<key>IDECodeSnippetUserSnippet</key>\n",
|
|
32
|
-
"\t<true/>\n",
|
|
33
|
-
"\t<key>IDECodeSnippetVersion</key>\n",
|
|
34
|
-
"\t<integer>2</integer>\n",
|
|
35
|
-
|
|
36
|
-
"</dict>\n",
|
|
37
|
-
"</plist>\n"
|
|
38
|
-
]
|
|
39
|
-
}
|