fuzzyworld

template / files / README.md

README.md

Blame: the commit that last changed each line · file · history

5c08eb8c 2023-02-18 Pavel Safronov1# README
2
3## Name
4
5template
6
7## Description
8
74911329 2023-04-10 Pavel Safronov9template is a command-line interface (CLI) tool that automates the creation of files and folders with pre-defined names and contents, so you can focus on your work and not on repetitive setup tasks.
5c08eb8c 2023-02-18 Pavel Safronov10
0621dedc 2026-01-15 Pavel Safronov11## Example
12
13For this example, pretend that today is April 14, 2025.
14
15```sh
16$ template daily "Cool Project"
17Profile: daily
18Project name: Cool Project
19Loaded config from /Users/pavel/.template.yaml
20Loaded user config from /Users/pavel/.template.user.yaml, combining with global config
21Creating file: /Users/pavel/DailyNotes/2025-04-04-Cool Project.md
22Executing post script: sh -c code . "/Users/pavel/DailyNotes/2025-04-04-Cool Project.md"
23Post script had no output
24```
25
26## Motivation
27
74911329 2023-04-10 Pavel Safronov28As developers and content creators, we often need to create files and folders with specific naming conventions, such as time-stamped file names, project-specific prefixes, and consistent suffixes. We also frequently need to populate these files with pre-defined contents, such as boilerplate code or templates for documentation. These tasks can be tedious and error-prone when done manually, especially when working on multiple projects or collaborating with others.
29
30template simplifies these tasks by providing a flexible and customizable way to create files and folders with consistent naming and content. With template, you can define your own naming patterns, file templates, and directory structures, or use pre-configured profiles that come with the tool. You can also pass in parameters at runtime to customize the output further, such as including a project name or arbitrary template data.
31
32template is built in Go and uses YAML and sprig templates for configuration. It supports creating both files and directories from predefined templates, as well as piped input for quick creation of files with custom content. With template, you can spend more time on your work and less time on setup and organization.
33
34## Usage
35
36To use template, you can run the template command followed by a profile name, parameters, and options. For example:
37
38```sh
39template daily "Cool Project"
40```
41
42This will create a new file in the format YYYY-MM-DD-cool_project.md in the ~/DailyNotes directory, with pre-defined contents.
43
44You can also define your own profiles in the ~/.template.yaml file, or specify file, directory, and script templates directly at runtime using the `-f`, `-d`, and `-s` options.
5c08eb8c 2023-02-18 Pavel Safronov45
46### Sample tool config
47
48This is one of the profiles that comes with the tool.
49
50```yaml
51 - name: daily
52 description: Creates a MD file in ~/DailyNotes folder in the format YYYY-MM-DD[-vX].md
53 isdefault: false
54 isdisabled: false
55 type: file
56 runpostscriptonfailure: true
57 postscripts:
58 - code . {{ if .FullPath }}"{{.FullPath}}"{{else}}(ls -t | head -n1){{ end }}
59 namepatterns:
2105a1d7 2023-04-02 Pavel Safronov60 - '{{$version := getVersion}}{{.YYYY_MM_DD}}{{if .ProjectName}}-{{.ProjectName | snakecase }}{{end}}{{if (gt $version 1)}}v{{$version}}{{end}}.md'
5c08eb8c 2023-02-18 Pavel Safronov61 targetdirectory: ~/DailyNotes
62 filetemplate: |-
63 # {{.FileNameWithoutExtension}}
64
2105a1d7 2023-04-02 Pavel Safronov65 Today's notes for {{.YYYY_MM_DD}}.
5c08eb8c 2023-02-18 Pavel Safronov66
67 ## Todo
68
69 1. Check email
70 2. Check chat
71 3. Check calendar
72 4. Check yesterday's notes
73 5. Have fun!
74 6. ADD MORE ITEMS HERE
75```
76
77Using the above configuration:
78
79```sh
80> $ template daily "Cool Thought"
81Profile: daily
82Project name: Cool Thought
5e132930 2023-03-29 Pavel Safronov83Loaded config from /Users/pavel/.template.yaml
84Loaded user config from /Users/pavel/.template.user.yaml, combining with global config
85Creating file: /Users/pavel/DailyNotes/2022-11-20-cool_thought.md
86Executing post script: sh -c code . "/Users/pavel/DailyNotes/2022-11-20-cool_thought.md"
5c08eb8c 2023-02-18 Pavel Safronov87Post script had no output
88```
89
90This will cause VSCode to open the `~\DailyNotes` folder as a workspace, and the newly-created file `2022-11-20-cool_thought.md` will be opened as well.
91
92The above example also uses the [`snakecase`](https://github.com/Masterminds/sprig/blob/master/docs/strings.md#user-content-snakecase) template function.
93This is one of the [sprig template functions](https://github.com/Masterminds/sprig/blob/master/docs/index.md) that are supported by template.
94
95File-based profiles (`type: file`) can accept piped input, and this input will be piped to the created file.
96In this instance, the profile's `FileTemplate` field is ignored.
97Here's an example of piping the results of `ps` to a file with an auto-generated name:
98
99```sh
100> $ echo "$(ps)" | template log "ps-info"
101Profile: log
102Project name: ps-info
5e132930 2023-03-29 Pavel Safronov103Loaded config from /Users/pavel/.template.yaml
104Loaded user config from /Users/pavel/.template.user.yaml, combining with global config
5c08eb8c 2023-02-18 Pavel Safronov105Creating file: 2022-12-10-00-05-21-ps-info.log
106Executing post script: sh -c code . 2022-12-10-00-05-21-ps-info.log
107Post script had no output
108```
109
110Note that user profiles are combined with the default ones.
111This is so you can run `template reset` to reset `~/.template.yaml`, but keep your local profiles/changes as-is.
112
8fc7c452 2023-03-29 Pavel Safronov113### Using a file or folder template directly
114
115You can also specify a file or folder template during execution, without changing any configs.
116
117Creating a file:
118
119```sh
120template -f "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}.txt" "project name"
121```
122
123Creating a folder:
124
125```sh
126template -d "{{.Year}}-{{.Month}}-{{.Day}}-{{.ProjectName}}.txt" Test123
127```
128
fd0a4446 2023-04-03 Pavel Safronov129### Using a script template directly
130
131You can also specify a template script:
132
133```sh
134template --script "echo 'Hello from {{.YYYY_MM_DD}}!'"
135```
136
137will result in:
138
139```txt
140> template --script "echo 'Hello from {{.YYYY_MM_DD}}!'"
141Project name:
142Loaded config from C:\Users\pavel\.template.yaml
143Loaded user config from C:\Users\pavel\.template.user.yaml, combining with global config
144Executing post script: cmd /c echo 'Hello from 2023-04-02!'
145Post script output: 'Hello from 2023-04-02!'
146
147```
148
5c08eb8c 2023-02-18 Pavel Safronov149## Examples
150
151### Use `daily` profile to create a new file
152
153```sh
154template daily
155```
156
157### Use `daily` profile to create a new file with a project name
158
159```sh
160template daily testing
161```
162
163### Use `daily` profile to create a new file with a project name that contains spaces
164
165```sh
166template daily "this is a test"
167```
168
169### Use `daily` profile to create a new file with contents piped in from `ps`
170
171```sh
172echo "$(ps)" | template daily
173```
174
175### Use `work` profile to create a folder with multiple files inside it
176
177```sh
178template work
179```
180
181### Use `work` profile and project name to create a folder with multiple files inside it
182
183```sh
184template work "fix-bug-123"
185```
186
187### Use `log` profile to create a `.log` from `stderr` and `stdout` from a `curl` command
188
189```sh
190curl -X GET "https://httpbin.org/delay/3" -H "accept: application/json" 2>&1 | template log
191```
192
8fc7c452 2023-03-29 Pavel Safronov193### Specify file pattern and project name
194
195```sh
fd0a4446 2023-04-03 Pavel Safronov196template -file "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}-{{.ProjectName}}.txt" test
8fc7c452 2023-03-29 Pavel Safronov197```
198
199### Specify file pattern, project name, and piped input
200
201```sh
fd0a4446 2023-04-03 Pavel Safronov202history | template -file "{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}-{{.ProjectName}}.txt" "Hi all!"
8fc7c452 2023-03-29 Pavel Safronov203```
204
205### Specify folder pattern and project name
206
207```sh
fd0a4446 2023-04-03 Pavel Safronov208template -dir "{{.Year}}-{{.Month}}-{{.Day}}-{{.ProjectName}}" test123
8fc7c452 2023-03-29 Pavel Safronov209```
210
5c08eb8c 2023-02-18 Pavel Safronov211## Requirements
212
213The application is a single executable, there are no special requirements.
214
215Building application requires [go](https://en.wikipedia.org/wiki/Go_(programming_language)). You can download the installer [here](https://go.dev/doc/install).
216
217The build is managed by [make](https://www.gnu.org/software/make/).
218
219The default profiles use [Visual Studio Code](https://code.visualstudio.com/) to open the generated files or folders.
220
221## Installation with Homebrew
222
223```sh
224brew tap PavelSafronov/template https://gitlab.com/PavelSafronov/template.git
225brew install template
226template reset
227```
228
229### Uninstall with Homebrew
230
231```sh
232brew uninstall template
233brew untap PavelSafronov/template
234```
235
d3c36d20 2023-02-18 Pavel Safronov236## Installation with Go
237
238If your Go installation is [properly configured](https://www.geeksforgeeks.org/how-to-install-a-package-with-go-get/), you can install `template` as a go module:
239
240```sh
241go install gitlab.com/PavelSafronov/template@latest
242```
243
2105a1d7 2023-04-02 Pavel Safronov244### Uninstall with go
245
246```sh
247go clean -i gitlab.com/PavelSafronov/template
248```
249
250## Manual installation
5c08eb8c 2023-02-18 Pavel Safronov251
2521. Navigate to [Releases](https://gitlab.com/PavelSafronov/template/-/releases)
2532. Choose the latest release
2543. Download the archive file `template_VERSION_OS.tar.gz`
2554. From the archive file, extract `template` to a location that's in your PATH
256
257## Installation with source
258
259Clone the repo and run these commands from the repo directory:
260
261```sh
262make install
0621dedc 2026-01-15 Pavel Safronov263```
264
265If this is your first installation or you want to reset your config to the default, run:
266
267```sh
5c08eb8c 2023-02-18 Pavel Safronov268template reset
269```
270
271### Uninstall with source
272
273To uninstall, run this command from the repo directory:
274
275```sh
276make uninstall
277```
278
279## Running after installation
280
281- `template` - uses default profile "note" to create a date-stamped MD file in current folder
282- `template blog` OR `template --profile blog` OR `template -p blog` - creates a date-stamped MD file in ~/Blog, opens in VSCode
283- `template daily topic` OR `template --profile daily --name topic` OR `template -p daily -n topic` - creates a templated date-stamped MD file with `topic` in its name in ~/DailyNotes, opens in VSCode
284- `template list` - lists all the found profiles
285- `template get profile2` - lists detailed information about profile `profile2`
05c30431 2026-01-16 Pavel Safronov286- `template init` - if global template config is not present, initializes the global template config with default profiles
5c08eb8c 2023-02-18 Pavel Safronov287- `template reset` - resets the configuration to the default config
288 - *Note*: this will overwrite whatever config changes you may have made
289 - *Note*: the defaults may change from version to version
290
291## Creating symbolic links
292
293template currently refers to paths under `~`. This is to ensure that it works on all systems.
294
295But I personally keep files in Dropbox, so I usually create symbolic links from (for example) `~/Blog` -> `~/Dropbox/Blog`. Here are the shell commands that I use, maybe they will be helpful for you. :)
296
bd9c08be 2023-08-29 Pavel Safronov297PowerShell commands to create symbolic links:
298
5c08eb8c 2023-02-18 Pavel Safronov299```powershell
bd9c08be 2023-08-29 Pavel Safronov300New-Item -ItemType Junction -Target (Resolve-Path "~\Dropbox\Blog") -Path "~\Blog\"
301New-Item -ItemType Junction -Target (Resolve-Path "~\Dropbox\DailyNotes") -Path "~\DailyNotes\"
302New-Item -ItemType Junction -Target (Resolve-Path "~\Dropbox\Notes") -Path "~\Notes\"
303New-Item -ItemType Junction -Target (Resolve-Path "~\Dropbox\Therapy") -Path "~\Therapy\"
304New-Item -ItemType Junction -Target (Resolve-Path "~\Dropbox\Work") -Path "~\Work\"
5c08eb8c 2023-02-18 Pavel Safronov305```
306
bd9c08be 2023-08-29 Pavel Safronov307Bash commands to create symbolic links:
308
5c08eb8c 2023-02-18 Pavel Safronov309```bash
310ln -s ~/Dropbox/Blog ~/Blog
311ln -s ~/Dropbox/DailyNotes ~/DailyNotes
312ln -s ~/Dropbox/Notes ~/Notes
313ln -s ~/Dropbox/Therapy ~/Therapy
314ln -s ~/Dropbox/Work ~/Work
315```
316
317## Dev loop
318
319A simple way to get started is to load this directory in VSCode and debug the project using one of the prepared launch tasks. Use command `View: Show Run and Debug` to display the launch configs, then pick one and press "Start Debugging" button.
320
321The following command will build the package, test it, and then install it:
322
323```sh
324make install
325```
326
8fc7c452 2023-03-29 Pavel Safronov327I use this approach, but that's because I use `template` multiple times a day, and find it helpful be using the latest version.
5c08eb8c 2023-02-18 Pavel Safronov328
329## Support
330
331For anything, open an issue in this repo.
332
8fc7c452 2023-03-29 Pavel Safronov333## Road map
5c08eb8c 2023-02-18 Pavel Safronov334
335I'm going to use this tool daily to figure out how it can be improved.
336
337While I am the only user, this app will stay at version `0.x.y`.
338At this point, breaking changes may happen.
339
340I'll try to use feature branches, but main will sometimes be in a broken state.
341Stable versions are tagged after I've had time to test it, so picking up those should be safe.
342
343Once there are enough other users and enough new feature requirements are added, we'll transition to version `1.x.y`.
344
345### Basic features
346
347Here are the basic features of the CLI that I want to keep:
348
8fc7c452 2023-03-29 Pavel Safronov3491. Cross-platform support
5c08eb8c 2023-02-18 Pavel Safronov3502. CLI is implemented in Go
3513. Fast (under 1s) basic operation of templating file and folder names
352 1. Postscripts can take longer, as long as the "basic operations" finish quickly enough.
353
354### KISS
355
356"Keep It Simple, Stupid"
357
358I want to keep this CLI simple. To that extent, I'm not interested in adding too many features. My main requirement right now is: `template blog topic` should do the same thing as `template --profile blog --name topic`.
359
2105a1d7 2023-04-02 Pavel Safronov360### Makefile and VSCode
5c08eb8c 2023-02-18 Pavel Safronov361
362Good guidance is invaluable, IMO, so to this extent I am very bullish about adding and using descriptive Makefile and VS Code launch tasks.
363
364Makefile should be used for any build/test/release task. If there is a reason to run a task more than once *in the lifetime of a project*, add the task to the Makefile with a descriptive name.
365I don't want to see complicated steps embedded in READMEs or (worse) in code.
366If the task is important, one that a maintainer/developer/user *may* want to do multiple times, add it to Makefile.
367
368Similarly, if there is a good VSCode debug scenario, add a task to launch.json.
369
370### Future Features
371
372Here is the future feature list:
373
3741. Publish Chocolatey version of app, possibly using [this GoReleaser Chocolatey documentation](https://goreleaser.com/customization/chocolatey/)
3752. Support for passing in a list of template values for custom values in the template. Use might look like this: `template work form123 --id=456 --corpOffice=SEA`. The passed-in extra values will be placed somewhere inside the template. Some value keys will not be allowed, like "time".
de118dc8 2023-04-20 Pavel Safronov3763. Add `template gen` to create templates from existing files/folders
3774. Add `template check` to verify that a given file matches a specific template
5c08eb8c 2023-02-18 Pavel Safronov378
2105a1d7 2023-04-02 Pavel Safronov379### Go module
380
381This project is mainly a CLI app written in Go, but it's also a Go module, so it can be used as a dependency.
382I'm not entirely sure why anyone would want to use this module instead of the CLI, but it's there.
383Please keep in mind that since my focus is on the CLI, CLI bugs and features will always be prioritized higher than module bugs and features.
384
5c08eb8c 2023-02-18 Pavel Safronov385## Contributing
386
387Contributions are welcome, but unsolicited PRs are not.
388If you want to add a particular feature, open an issue first and suggest it.
389We'll discuss the feature and if I agree that it should be added, you can open a PR.
390
391I don't want to waste my time or your time.
392
393## Authors and acknowledgment
394
395Your name will be listed here if you contribute.
396
397## License
398
399MIT license.
400
401## Project status
402
403This was a hackathon project to learn Go.
404I'm going to be using this tool and upgrading it as I see fit.