Skip to content

Commit dacffa7

Browse files
committed
feat: Add support for saga init .
1 parent dd09b78 commit dacffa7

2 files changed

Lines changed: 33 additions & 27 deletions

File tree

Sources/SagaCLI/InitCommand.swift

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,43 +6,54 @@ struct Init: ParsableCommand {
66
abstract: "Create a new Saga project."
77
)
88

9-
@Argument(help: "The name of the project to create.")
9+
@Argument(help: "The name of the project to create, or '.' to create it in the current folder.")
1010
var name: String
1111

1212
func run() throws {
13-
let projectPath = Path.current + name
13+
let createInPlace = name == "."
14+
let projectPath = createInPlace ? Path.current : Path.current + name
1415

15-
guard !projectPath.exists else {
16-
throw ValidationError("Directory '\(name)' already exists.")
16+
if !createInPlace {
17+
guard !projectPath.exists else {
18+
throw ValidationError("Directory '\(name)' already exists.")
19+
}
1720
}
1821

19-
let capitalizedName = name.prefix(1).uppercased() + name.dropFirst()
22+
let projectName = createInPlace ? projectPath.absolute().lastComponent : name
23+
24+
guard let firstCharacter = projectName.first, firstCharacter.isLetter || firstCharacter.isNumber else {
25+
throw ValidationError("Could not determine a project name from the current folder.")
26+
}
27+
28+
let capitalizedName = projectName.prefix(1).uppercased() + projectName.dropFirst()
29+
30+
let files: [(Path, String)] = [
31+
(Path("Package.swift"), ProjectTemplate.packageSwift(name: capitalizedName)),
32+
(Path("Sources") + capitalizedName + "main.swift", ProjectTemplate.mainSwift(name: capitalizedName)),
33+
(Path("Sources") + capitalizedName + "templates.swift", ProjectTemplate.templatesSwift()),
34+
(Path("content") + "index.md", ProjectTemplate.indexMarkdown()),
35+
(Path("content") + "articles" + "hello-world.md", ProjectTemplate.helloWorldMarkdown()),
36+
(Path("content") + "static" + "style.css", ProjectTemplate.styleCss()),
37+
(Path("README.md"), ProjectTemplate.readme(name: capitalizedName)),
38+
(Path(".gitignore"), ProjectTemplate.gitignore()),
39+
]
2040

2141
// Create directory structure
2242
try (projectPath + "Sources" + capitalizedName).mkpath()
2343
try (projectPath + "content" + "articles").mkpath()
2444
try (projectPath + "content" + "static").mkpath()
2545

2646
// Write files
27-
let files: [(Path, String)] = [
28-
(projectPath + "Package.swift", ProjectTemplate.packageSwift(name: capitalizedName)),
29-
(projectPath + "Sources" + capitalizedName + "main.swift", ProjectTemplate.mainSwift(name: capitalizedName)),
30-
(projectPath + "Sources" + capitalizedName + "templates.swift", ProjectTemplate.templatesSwift()),
31-
(projectPath + "content" + "index.md", ProjectTemplate.indexMarkdown()),
32-
(projectPath + "content" + "articles" + "hello-world.md", ProjectTemplate.helloWorldMarkdown()),
33-
(projectPath + "content" + "static" + "style.css", ProjectTemplate.styleCss()),
34-
(projectPath + "README.md", ProjectTemplate.readme(name: capitalizedName)),
35-
(projectPath + ".gitignore", ProjectTemplate.gitignore()),
36-
]
37-
3847
for (path, content) in files {
39-
try path.write(content)
48+
try (projectPath + path).write(content)
4049
}
4150

42-
print("Created new Saga project in '\(name)/'")
51+
print("Created new Saga project in '\(createInPlace ? projectPath.absolute().lastComponent : name)/'")
4352
print("")
4453
print("Next steps:")
45-
print(" cd \(name)")
54+
if !createInPlace {
55+
print(" cd \(name)")
56+
}
4657
print(" saga dev")
4758
}
4859
}

Sources/SagaCLI/ProjectTemplate.swift

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -382,23 +382,18 @@ enum ProjectTemplate {
382382
383383
## How it works
384384
385-
Saga runs a **Reader → Processor → Writer** pipeline. Every `register` step in `main.swift` claims
386-
a folder of content, parses it into typed items, and hands those items to writers that render HTML:
385+
Saga runs a **Reader → Processor → Writer** pipeline. Every `register` step in `main.swift` claims a folder of content, parses it into typed items, and hands those items to writers that render HTML:
387386
388-
- `content/articles/*.md` is read into `Item<ArticleMetadata>` values, and written to
389-
`/articles/<slug>/`, plus an index at `/articles/` and a page per tag at `/articles/tag/<tag>/`.
387+
- `content/articles/*.md` is read into `Item<ArticleMetadata>` values, and written to `/articles/<slug>/`, plus an index at `/articles/` and a page per tag at `/articles/tag/<tag>/`.
390388
- Every other markdown file is written as a standalone page, so `content/index.md` becomes `/`.
391389
392-
Metadata comes from the YAML front matter at the top of each markdown file. Add a field to
393-
`ArticleMetadata` in `main.swift` to make it available in your templates.
390+
Metadata comes from the YAML front matter at the top of each markdown file. Add a field to `ArticleMetadata` in `main.swift` to make it available in your templates.
394391
395392
Anything in `content/static/` that no step claims is copied to `deploy/` untouched.
396393
397394
## Learn more
398395
399-
- [Documentation](https://getsaga.dev/docs/)
400396
- [Getting started](https://getsaga.dev/docs/gettingstarted/)
401-
- [Architecture](https://getsaga.dev/docs/architecture/)
402397
- [Guides](https://getsaga.dev/docs/guides/) — search, sitemaps, syntax highlighting, Tailwind CSS, and more
403398
"""
404399
}

0 commit comments

Comments
 (0)