fuzzyworld

template / commit

Adding two new patterns: YYYY_MM_DD and YYYY_MM_DD_HH_MM_SS, which produce sortable kebab-case date/datetime strings.

2105a1d701e0ce116f040087e5fdd01efa3c3de6 · Pavel Safronov · 2023-04-02 09:51:05 -0700 · parents 5e1329303fae

Adding two new patterns: YYYY_MM_DD and YYYY_MM_DD_HH_MM_SS, which produce sortable kebab-case date/datetime strings.
Minor test updates and a bit of a refactor.
Update the readme to include go uninstall instructions.
 README.md            |  24 ++-
 default_config.go    | 576 +++++++++++++++++++++++++--------------------------
 main_test.go         |  22 +-
 name_pattern_test.go |  78 ++-----
 parameter_data.go    |  75 ++++---
 profile.go           |  14 --
 6 files changed, 386 insertions(+), 403 deletions(-)

diff --git a/README.md b/README.md
index 9f0f555..11bba29 100644
--- a/README.md
+++ b/README.md
@@ -11,10 +11,6 @@ It's also possible to control the contents of the files: you can specify a templ
 
 This started as a hackathon project that I used to learn Go (golang) and to automate a repetitive task: creation of time-stamped files and folders.
 
-This project is mainly a CLI app written in Go, but it's also a Go module, so it can be used as a dependency.

-I'm not entirely sure why anyone would want to use this module instead of the CLI, but it's there.

-Please 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.

-

 ### Sample tool config
 
 This is one of the profiles that comes with the tool.
@@ -29,12 +25,12 @@ This is one of the profiles that comes with the tool.
       postscripts:
         - code . {{ if .FullPath }}"{{.FullPath}}"{{else}}(ls -t | head -n1){{ end }}
       namepatterns:
-        - '{{$version := getVersion}}{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName | snakecase }}{{end}}{{if (gt $version 1)}}v{{$version}}{{end}}.md'

+        - '{{$version := getVersion}}{{.YYYY_MM_DD}}{{if .ProjectName}}-{{.ProjectName | snakecase }}{{end}}{{if (gt $version 1)}}v{{$version}}{{end}}.md'

       targetdirectory: ~/DailyNotes
       filetemplate: |-
         # {{.FileNameWithoutExtension}}
 
-        Today's notes for {{.Year}}-{{.Month}}-{{.Day}}.

+        Today's notes for {{.YYYY_MM_DD}}.

 
         ## Todo
 
@@ -193,7 +189,13 @@ If your Go installation is [properly configured](https://www.geeksforgeeks.org/h
 go install gitlab.com/PavelSafronov/template@latest
 ```
 
-## Manual Installation

+### Uninstall with go

+

+```sh

+go clean -i gitlab.com/PavelSafronov/template

+```

+

+## Manual installation

 
 1. Navigate to [Releases](https://gitlab.com/PavelSafronov/template/-/releases)
 2. Choose the latest release
@@ -293,7 +295,7 @@ Here are the basic features of the CLI that I want to keep:
 
 I 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`.
 
-### VSCode and make

+### Makefile and VSCode

 
 Good guidance is invaluable, IMO, so to this extent I am very bullish about adding and using descriptive Makefile and VS Code launch tasks.
 
@@ -310,6 +312,12 @@ Here is the future feature list:
 1. Publish Chocolatey version of app, possibly using [this GoReleaser Chocolatey documentation](https://goreleaser.com/customization/chocolatey/)
 2. 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".
 
+### Go module

+

+This project is mainly a CLI app written in Go, but it's also a Go module, so it can be used as a dependency.

+I'm not entirely sure why anyone would want to use this module instead of the CLI, but it's there.

+Please 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.

+

 ## Contributing
 
 Contributions are welcome, but unsolicited PRs are not.
diff --git a/default_config.go b/default_config.go
index 3791e61..b2c7a68 100644
--- a/default_config.go
+++ b/default_config.go
@@ -1,288 +1,288 @@
-package main
-
-func defaultConfig() Config {
-	config := Config{
-		Profiles: []Profile{
-			{
-				Name:            "daily",
-				Description:     "Creates a MD file in ~/DailyNotes folder in the format YYYY-MM-DD[-vX].md",
-				TargetDirectory: "~/DailyNotes",
-				Type:            FileType,
-				NamePatterns: []ParameterizedText{
-					"{{$version := getVersion}}" +
-						"{{.Year}}-{{.Month}}-{{.Day}}" +
-						`{{if .ProjectName}}-{{.ProjectName | snakecase }}{{end}}` +
-						"{{if (gt $version 1)}}v{{$version}}{{end}}" +
-						".md",
-				},
-				FileTemplate: `# {{.FileNameWithoutExtension}}
-
-Today's notes for {{.Year}}-{{.Month}}-{{.Day}}.
-
-## Todo
-
-1. Check email
-2. Check chat
-3. Check calendar
-4. Check yesterday's notes
-5. Have fun!
-6. ADD MORE ITEMS HERE`,
-				PostScripts: []ParameterizedText{
-					"code . {{ if .FullPath }}\"{{.FullPath}}\"{{else}}(ls -t | head -n1){{ end }}",
-				},
-				RunPostscriptOnFailure: true,
-			},
-			{
-				Name:            "note",
-				Description:     "Creates a MD file in ~/Notes in the format YYYY-MM-DD[-ProjectName][-vVersion].md",
-				OS:              "All",
-				TargetDirectory: "~/Notes",
-				Type:            FileType,
-				NamePatterns: []ParameterizedText{
-					"{{$version := getVersion}}" +
-						"{{.Year}}-{{.Month}}-{{.Day}}" +
-						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +
-						"{{if (gt $version 1)}}n{{$version}}{{end}}" +
-						".md",
-				},
-				PostScripts: []ParameterizedText{
-					"code \"{{.FullPath}}\"",
-				},
-			},
-			{
-				Name:            "note-here",
-				Description:     "Creates a MD file in the current folder in the format YYYY-MM-DD[-HH[-MM[-SS]]][-ProjectName][-vVersion].md",
-				OS:              "All",
-				Type:            FileType,
-				IsDefault:       true,
-				TargetDirectory: ".", // current folder
-				NamePatterns: []ParameterizedText{
-					"{{$version := getVersion}}" +
-						"{{.Year}}-{{.Month}}-{{.Day}}" +
-						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +
-						"{{if (gt $version 1)}}n{{$version}}{{end}}" +
-						".md",
-					"{{$version := getVersion}}" +
-						"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}" +
-						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +
-						"{{if (gt $version 1)}}n{{$version}}{{end}}" +
-						".md",
-					"{{$version := getVersion}}" +
-						"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}" +
-						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +
-						"{{if (gt $version 1)}}n{{$version}}{{end}}" +
-						".md",
-					"{{$version := getVersion}}" +
-						"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}" +
-						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +
-						"{{if (gt $version 1)}}n{{$version}}{{end}}" +
-						".md",
-				},
-				PostScripts: []ParameterizedText{
-					"code \"{{.FullPath}}\"",
-				},
-			},
-			{
-				Name:            "blog",
-				Description:     "Creates a MD file in the ~/Blog folder in the format YYYY-MM-DD[-ProjectName][-vVersion].md",
-				OS:              "All",
-				TargetDirectory: "~/Blog",
-				FileTemplate: `# {{.ProjectName}}
-
-Created by template, on {{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}.
-
-## Spelling
-
-cspell:words nanite
-
-## Removed writing
-
-## Writing
-`,
-				Type: FileType,
-				NamePatterns: []ParameterizedText{
-					"{{$version := getVersion}}" +
-						"{{.Year}}-{{.Month}}-{{.Day}}" +
-						`{{if .ProjectName}}-{{.ProjectName | snakecase }}{{end}}` +
-						"{{if (gt $version 1)}}v{{$version}}{{end}}" +
-						".md",
-				},
-				PostScripts: []ParameterizedText{
-					"code . \"{{.FileName}}\"",
-				},
-			},
-			{
-				Name:            "work-win",
-				Description:     "Creates a folder in the c:/work folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]",
-				OS:              "Windows",
-				TargetDirectory: "C:/work",
-				Type:            FolderType,
-				NamePatterns: []ParameterizedText{
-					"{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-				},
-				PostScripts: []ParameterizedText{
-					"explorer \"{{.Path}}\"",
-				},
-			},
-			{
-				Name:            "therapy",
-				Description:     "Creates a MD file in the ~/Therapy folder in the format YYYY-MM-DD[-vVersion].md",
-				OS:              "All",
-				TargetDirectory: "~/Therapy",
-				FileTemplate: `# {{if .ProjectName}}{{.ProjectName}}{{else}}Therapy notes{{end}}
-
-{{if .ProjectName}}Therapy notes on {{.ProjectName}}{{else}}Therapy notes{{end}}
-
-## Spelling
-
-cspell:words cromulent embiggen
-
-## Writing
-
-{{if .ProjectName}}Hello {{.ProjectName}},{{else}}Hello,{{end}}
-
-Start writing here...
-
-Sincerely, me
-`,
-				Type: FileType,
-				NamePatterns: []ParameterizedText{
-					"{{$version := getVersion}}" +
-						"{{.Year}}-{{.Month}}-{{.Day}}" +
-						"{{if (gt $version 1)}}v{{$version}}{{end}}" +
-						".md",
-				},
-				PostScripts: []ParameterizedText{
-					"code . {{.FullPath}}",
-				},
-			},
-			{
-				Name:            "work",
-				Description:     "Creates a folder in the ~/Work folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]",
-				TargetDirectory: "~/Work",
-				Type:            FolderType,
-				NamePatterns: []ParameterizedText{
-					"{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-				},
-				PostScripts: []ParameterizedText{
-					"code .",
-					"chmod +x repro.sh",
-				},
-				Files: []FileInFolder{
-					{
-						FileTemplate: `# {{.ProjectName}}
-
-Work notes on {{.ProjectName}}
-`,
-						Name: "README.md",
-					},
-					{
-						FileTemplate: `clear
-
-echo "Let's test {{.ProjectName}}!"`,
-						Name: "repro.sh",
-					},
-					{
-						FileTemplate: `{
-    "version": "0.2.0",
-    "configurations": [
-        {
-            "type": "bashdb",
-            "request": "launch",
-            "name": "Debug repo.sh",
-            "cwd": "${workspaceFolder}",
-            "program": "${workspaceFolder}/repro.sh",
-            "terminalKind": "integrated"
-        }
-    ]
-}
-							`,
-						Name: ".vscode/launch.json",
-					},
-				},
-			},
-			{
-				Name:            "folder",
-				Description:     "Creates a folder in the current folder in the format YYYY-MM-DD[-ProjectName][-vVersion]",
-				Type:            FolderType,
-				TargetDirectory: ".", // current folder
-				PostScripts:     []ParameterizedText{},
-				NamePatterns: []ParameterizedText{
-					"{{$version := getVersion}}" +
-						"{{.Year}}-{{.Month}}-{{.Day}}" +
-						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +
-						"{{if (gt $version 1)}}-n{{$version}}{{end}}",
-				},
-			},
-			{
-				Name:            "create-react-app",
-				Type:            FolderType,
-				Description:     "Creates a folder in the current folder in the format create-react-app[-ProjectName][-vVersion], runs `npx create-react-app` to initialize the folder, and opens the folder in VSCode",
-				TargetDirectory: ".", // current folder
-				NamePatterns: []ParameterizedText{
-					"{{$version := getVersion}}" +
-						"create-react-app" +
-						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +
-						"{{if (gt $version 1)}}-n{{$version}}{{end}}",
-				},
-				PostScripts: []ParameterizedText{
-					"npx create-react-app .",
-					"code .",
-				},
-			},
-			{
-				Name:            "git",
-				Description:     "Creates a  folder in the ~/code folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]",
-				TargetDirectory: "~/code",
-				Type:            FolderType,
-				NamePatterns: []ParameterizedText{
-					"{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-				},
-				PostScripts: []ParameterizedText{
-					"git init",
-					"code .",
-				},
-			},
-			{
-				Name:            "git-clone",
-				Description:     "DISABLED - Clones a repository into a new folder under ~/code in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]",
-				IsDisabled:      true,
-				TargetDirectory: "~/code",
-				Type:            FolderType,
-				NamePatterns: []ParameterizedText{
-					"{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",
-				},
-				PostScripts: []ParameterizedText{
-					"git clone {{.Url}} .",
-					"code .",
-				},
-			},
-			{
-				Name:        "log",
-				Description: "Creates a log file in the current folder",
-				Type:        FileType,
-				NamePatterns: []ParameterizedText{
-					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}.log",
-				},
-				TargetDirectory: ".",
-				PostScripts: []ParameterizedText{
-					"code . {{.FullPath}}",
-				},
-			},
-		},
-	}
-
-	return config
-}
+package main

+

+func defaultConfig() Config {

+	config := Config{

+		Profiles: []Profile{

+			{

+				Name:            "daily",

+				Description:     "Creates a MD file in ~/DailyNotes folder in the format YYYY-MM-DD[-vX].md",

+				TargetDirectory: "~/DailyNotes",

+				Type:            FileType,

+				NamePatterns: []ParameterizedText{

+					"{{$version := getVersion}}" +

+						"{{.YYYY_MM_DD}}" +

+						`{{if .ProjectName}}-{{.ProjectName | snakecase }}{{end}}` +

+						"{{if (gt $version 1)}}v{{$version}}{{end}}" +

+						".md",

+				},

+				FileTemplate: `# {{.FileNameWithoutExtension}}

+

+Today's notes for {{.Year}}-{{.Month}}-{{.Day}}.

+

+## Todo

+

+1. Check email

+2. Check chat

+3. Check calendar

+4. Check yesterday's notes

+5. Have fun!

+6. ADD MORE ITEMS HERE`,

+				PostScripts: []ParameterizedText{

+					"code . {{ if .FullPath }}\"{{.FullPath}}\"{{else}}(ls -t | head -n1){{ end }}",

+				},

+				RunPostscriptOnFailure: true,

+			},

+			{

+				Name:            "note",

+				Description:     "Creates a MD file in ~/Notes in the format YYYY-MM-DD[-ProjectName][-vVersion].md",

+				OS:              "All",

+				TargetDirectory: "~/Notes",

+				Type:            FileType,

+				NamePatterns: []ParameterizedText{

+					"{{$version := getVersion}}" +

+						"{{.Year}}-{{.Month}}-{{.Day}}" +

+						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +

+						"{{if (gt $version 1)}}n{{$version}}{{end}}" +

+						".md",

+				},

+				PostScripts: []ParameterizedText{

+					"code \"{{.FullPath}}\"",

+				},

+			},

+			{

+				Name:            "note-here",

+				Description:     "Creates a MD file in the current folder in the format YYYY-MM-DD[-HH[-MM[-SS]]][-ProjectName][-vVersion].md",

+				OS:              "All",

+				Type:            FileType,

+				IsDefault:       true,

+				TargetDirectory: ".", // current folder

+				NamePatterns: []ParameterizedText{

+					"{{$version := getVersion}}" +

+						"{{.Year}}-{{.Month}}-{{.Day}}" +

+						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +

+						"{{if (gt $version 1)}}n{{$version}}{{end}}" +

+						".md",

+					"{{$version := getVersion}}" +

+						"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}" +

+						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +

+						"{{if (gt $version 1)}}n{{$version}}{{end}}" +

+						".md",

+					"{{$version := getVersion}}" +

+						"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}" +

+						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +

+						"{{if (gt $version 1)}}n{{$version}}{{end}}" +

+						".md",

+					"{{$version := getVersion}}" +

+						"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}" +

+						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +

+						"{{if (gt $version 1)}}n{{$version}}{{end}}" +

+						".md",

+				},

+				PostScripts: []ParameterizedText{

+					"code \"{{.FullPath}}\"",

+				},

+			},

+			{

+				Name:            "blog",

+				Description:     "Creates a MD file in the ~/Blog folder in the format YYYY-MM-DD[-ProjectName][-vVersion].md",

+				OS:              "All",

+				TargetDirectory: "~/Blog",

+				FileTemplate: `# {{.ProjectName}}

+

+Created by template, on {{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}.

+

+## Spelling

+

+cspell:words nanite

+

+## Removed writing

+

+## Writing

+`,

+				Type: FileType,

+				NamePatterns: []ParameterizedText{

+					"{{$version := getVersion}}" +

+						"{{.Year}}-{{.Month}}-{{.Day}}" +

+						`{{if .ProjectName}}-{{.ProjectName | snakecase }}{{end}}` +

+						"{{if (gt $version 1)}}v{{$version}}{{end}}" +

+						".md",

+				},

+				PostScripts: []ParameterizedText{

+					"code . \"{{.FileName}}\"",

+				},

+			},

+			{

+				Name:            "work-win",

+				Description:     "Creates a folder in the c:/work folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]",

+				OS:              "Windows",

+				TargetDirectory: "C:/work",

+				Type:            FolderType,

+				NamePatterns: []ParameterizedText{

+					"{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+				},

+				PostScripts: []ParameterizedText{

+					"explorer \"{{.Path}}\"",

+				},

+			},

+			{

+				Name:            "therapy",

+				Description:     "Creates a MD file in the ~/Therapy folder in the format YYYY-MM-DD[-vVersion].md",

+				OS:              "All",

+				TargetDirectory: "~/Therapy",

+				FileTemplate: `# {{if .ProjectName}}{{.ProjectName}}{{else}}Therapy notes{{end}}

+

+{{if .ProjectName}}Therapy notes on {{.ProjectName}}{{else}}Therapy notes{{end}}

+

+## Spelling

+

+cspell:words cromulent embiggen

+

+## Writing

+

+{{if .ProjectName}}Hello {{.ProjectName}},{{else}}Hello,{{end}}

+

+Start writing here...

+

+Sincerely, me

+`,

+				Type: FileType,

+				NamePatterns: []ParameterizedText{

+					"{{$version := getVersion}}" +

+						"{{.Year}}-{{.Month}}-{{.Day}}" +

+						"{{if (gt $version 1)}}v{{$version}}{{end}}" +

+						".md",

+				},

+				PostScripts: []ParameterizedText{

+					"code . {{.FullPath}}",

+				},

+			},

+			{

+				Name:            "work",

+				Description:     "Creates a folder in the ~/Work folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]",

+				TargetDirectory: "~/Work",

+				Type:            FolderType,

+				NamePatterns: []ParameterizedText{

+					"{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+				},

+				PostScripts: []ParameterizedText{

+					"code .",

+					"chmod +x repro.sh",

+				},

+				Files: []FileInFolder{

+					{

+						FileTemplate: `# {{.ProjectName}}

+

+Work notes on {{.ProjectName}}

+`,

+						Name: "README.md",

+					},

+					{

+						FileTemplate: `clear

+

+echo "Let's test {{.ProjectName}}!"`,

+						Name: "repro.sh",

+					},

+					{

+						FileTemplate: `{

+    "version": "0.2.0",

+    "configurations": [

+        {

+            "type": "bashdb",

+            "request": "launch",

+            "name": "Debug repo.sh",

+            "cwd": "${workspaceFolder}",

+            "program": "${workspaceFolder}/repro.sh",

+            "terminalKind": "integrated"

+        }

+    ]

+}

+							`,

+						Name: ".vscode/launch.json",

+					},

+				},

+			},

+			{

+				Name:            "folder",

+				Description:     "Creates a folder in the current folder in the format YYYY-MM-DD[-ProjectName][-vVersion]",

+				Type:            FolderType,

+				TargetDirectory: ".", // current folder

+				PostScripts:     []ParameterizedText{},

+				NamePatterns: []ParameterizedText{

+					"{{$version := getVersion}}" +

+						"{{.Year}}-{{.Month}}-{{.Day}}" +

+						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +

+						"{{if (gt $version 1)}}-n{{$version}}{{end}}",

+				},

+			},

+			{

+				Name:            "create-react-app",

+				Type:            FolderType,

+				Description:     "Creates a folder in the current folder in the format create-react-app[-ProjectName][-vVersion], runs `npx create-react-app` to initialize the folder, and opens the folder in VSCode",

+				TargetDirectory: ".", // current folder

+				NamePatterns: []ParameterizedText{

+					"{{$version := getVersion}}" +

+						"create-react-app" +

+						"{{if .ProjectName}}-{{.ProjectName}}{{end}}" +

+						"{{if (gt $version 1)}}-n{{$version}}{{end}}",

+				},

+				PostScripts: []ParameterizedText{

+					"npx create-react-app .",

+					"code .",

+				},

+			},

+			{

+				Name:            "git",

+				Description:     "Creates a  folder in the ~/code folder in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]",

+				TargetDirectory: "~/code",

+				Type:            FolderType,

+				NamePatterns: []ParameterizedText{

+					"{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+				},

+				PostScripts: []ParameterizedText{

+					"git init",

+					"code .",

+				},

+			},

+			{

+				Name:            "git-clone",

+				Description:     "DISABLED - Clones a repository into a new folder under ~/code in the format YYYY-MM-DD[-hh][-mm][-ss][-ProjectName]",

+				IsDisabled:      true,

+				TargetDirectory: "~/code",

+				Type:            FolderType,

+				NamePatterns: []ParameterizedText{

+					"{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}",

+				},

+				PostScripts: []ParameterizedText{

+					"git clone {{.Url}} .",

+					"code .",

+				},

+			},

+			{

+				Name:        "log",

+				Description: "Creates a log file in the current folder",

+				Type:        FileType,

+				NamePatterns: []ParameterizedText{

+					"{{.Year}}-{{.Month}}-{{.Day}}-{{.Hour}}-{{.Minute}}-{{.Second}}{{if .ProjectName}}-{{.ProjectName}}{{end}}.log",

+				},

+				TargetDirectory: ".",

+				PostScripts: []ParameterizedText{

+					"code . {{.FullPath}}",

+				},

+			},

+		},

+	}

+

+	return config

+}

diff --git a/main_test.go b/main_test.go
index fa619e2..ac1aa3f 100644
--- a/main_test.go
+++ b/main_test.go
@@ -4,7 +4,7 @@ import (
 	"os"
 	"testing"
 
-	"github.com/stretchr/testify/require"

+	"github.com/stretchr/testify/assert"

 )
 
 func TestMain(m *testing.M) {
@@ -31,11 +31,11 @@ func TestFindProfile(t *testing.T) {
 			fileTemplate: fileTemplate,
 		},
 	})
-	require.NoError(t, err)

-	require.Equal(t, "temp", profile.Name)

-	require.Equal(t, FileType, profile.Type)

-	require.Equal(t, 1, len(profile.NamePatterns))

-	require.Equal(t, ParameterizedText(fileTemplate), profile.NamePatterns[0])

+	assert.NoError(t, err)

+	assert.Equal(t, "temp", profile.Name)

+	assert.Equal(t, FileType, profile.Type)

+	assert.Equal(t, 1, len(profile.NamePatterns))

+	assert.Equal(t, ParameterizedText(fileTemplate), profile.NamePatterns[0])

 
 	dirTemplate := "{{.Year}}-{{.Month}}-{{.Day}}{{if .ProjectName}}-{{.ProjectName}}{{end}}"
 	profile, err = findProfile(Settings{
@@ -43,9 +43,9 @@ func TestFindProfile(t *testing.T) {
 			dirTemplate: dirTemplate,
 		},
 	})
-	require.NoError(t, err)

-	require.Equal(t, "temp", profile.Name)

-	require.Equal(t, FolderType, profile.Type)

-	require.Equal(t, 1, len(profile.NamePatterns))

-	require.Equal(t, ParameterizedText(dirTemplate), profile.NamePatterns[0])

+	assert.NoError(t, err)

+	assert.Equal(t, "temp", profile.Name)

+	assert.Equal(t, FolderType, profile.Type)

+	assert.Equal(t, 1, len(profile.NamePatterns))

+	assert.Equal(t, ParameterizedText(dirTemplate), profile.NamePatterns[0])

 }
diff --git a/name_pattern_test.go b/name_pattern_test.go
index 3a6ef6f..9dfb76e 100644
--- a/name_pattern_test.go
+++ b/name_pattern_test.go
@@ -36,34 +36,18 @@ func TestCreateNewName(t *testing.T) {
 			prePatternData := createPrePatternData(now, projectName, extras)
 			validator := func(newName string) bool { return !slices.Contains(existingEntities, newName) }
 			newName, err := createNewNameForPatterns(now, prePatternData, projectName, profile.NamePatterns, extras, validator)
-			if err != nil {

-				t.Error("Error creating new name: ", err)

-			}

-			if newName != expectedName {

-				t.Error("Expected name to be ", expectedName, " but got ", newName)

-			}

-			if prePatternData.ProjectName != projectName {

-				t.Error("Expected prePatternData.ProjectName to be ", projectName, " but got ", prePatternData.ProjectName)

-			}

-			if prePatternData.Year != "2006" {

-				t.Error("Expected prePatternData.Year to be 2006 but got ", prePatternData.Year)

-			}

-			if prePatternData.Month != "01" {

-				t.Error("Expected prePatternData.Month to be 01 but got ", prePatternData.Month)

-			}

-			if prePatternData.Day != "02" {

-				t.Error("Expected prePatternData.Day to be 02 but got ", prePatternData.Day)

-			}

-			if prePatternData.Hour != "15" {

-				t.Error("Expected prePatternData.Hour to be 15 but got ", prePatternData.Hour)

-			}

-			if prePatternData.Minute != "04" {

-				t.Error("Expected prePatternData.Minute to be 04 but got ", prePatternData.Minute)

-			}

-			if prePatternData.Second != "05" {

-				t.Error("Expected prePatternData.Second to be 05 but got ", prePatternData.Second)

-			}

-

+			assert.NoError(t, err)

+			assert.Equal(t, expectedName, newName, "generated name")

+			assert.Equal(t, projectName, prePatternData.ProjectName, "project name")

+			assert.Equal(t, "2006", prePatternData.Year, "year")

+			assert.Equal(t, "01", prePatternData.Month, "month")

+			assert.Equal(t, "02", prePatternData.Day, "day")

+			assert.Equal(t, "15", prePatternData.Hour, "hour")

+			assert.Equal(t, "04", prePatternData.Minute, "minute")

+			assert.Equal(t, "05", prePatternData.Second, "second")

+			assert.Equal(t, "2006-01-02", prePatternData.YYYY_MM_DD, "YYYY_MM_DD")

+			assert.Equal(t, "2006-01-02-15-04-05", prePatternData.YYYY_MM_DD_HH_MM_SS, "YYYY_MM_DD_HH_MM_SS")

+			assert.Equal(t, "test1", prePatternData.Extras["test1"], "test1")

 		}
 	}
 	testErrorPath := func(projectName string, existingEntities []string) func(t *testing.T) {
@@ -109,33 +93,17 @@ func TestCreateNewName_Index(t *testing.T) {
 			prePatternData := createPrePatternData(now, "test-project", extras)
 			validator := func(newName string) bool { return !slices.Contains(existingEntities, newName) }
 			newName, err := createNewNameForPatterns(now, prePatternData, "test-project", profile.NamePatterns, extras, validator)
-			if err != nil {

-				t.Error("Error creating new name: ", err)

-			}

-			if newName != expectedName {

-				t.Error("Expected name to be ", expectedName, " but got ", newName)

-			}

-			if prePatternData.ProjectName != "test-project" {

-				t.Error("Expected prePatternData.ProjectName to be test-project but got ", prePatternData.ProjectName)

-			}

-			if prePatternData.Year != "2006" {

-				t.Error("Expected prePatternData.Year to be 2006 but got ", prePatternData.Year)

-			}

-			if prePatternData.Month != "01" {

-				t.Error("Expected prePatternData.Month to be 01 but got ", prePatternData.Month)

-			}

-			if prePatternData.Day != "02" {

-				t.Error("Expected prePatternData.Day to be 02 but got ", prePatternData.Day)

-			}

-			if prePatternData.Hour != "15" {

-				t.Error("Expected prePatternData.Hour to be 15 but got ", prePatternData.Hour)

-			}

-			if prePatternData.Minute != "04" {

-				t.Error("Expected prePatternData.Minute to be 04 but got ", prePatternData.Minute)

-			}

-			if prePatternData.Second != "05" {

-				t.Error("Expected prePatternData.Second to be 05 but got ", prePatternData.Second)

-			}

+			assert.NoError(t, err)

+			assert.Equal(t, expectedName, newName, "generated name")

+			assert.Equal(t, "test-project", prePatternData.ProjectName, "project name")

+			assert.Equal(t, "2006", prePatternData.Year, "year")

+			assert.Equal(t, "01", prePatternData.Month, "month")

+			assert.Equal(t, "02", prePatternData.Day, "day")

+			assert.Equal(t, "15", prePatternData.Hour, "hour")

+			assert.Equal(t, "04", prePatternData.Minute, "minute")

+			assert.Equal(t, "05", prePatternData.Second, "second")

+			assert.Equal(t, "2006-01-02", prePatternData.YYYY_MM_DD, "YYYY_MM_DD")

+			assert.Equal(t, "2006-01-02-15-04-05", prePatternData.YYYY_MM_DD_HH_MM_SS, "YYYY_MM_DD_HH_MM_SS")

 		}
 	}
 
diff --git a/parameter_data.go b/parameter_data.go
index d4b5f09..0f5c4d0 100644
--- a/parameter_data.go
+++ b/parameter_data.go
@@ -1,27 +1,48 @@
-package main
-
-import "path/filepath"
-
-type PrePatternData struct {
-	ProjectName                            string
-	Year, Month, Day, Hour, Minute, Second string
-	Extras                                 map[string]string
-}
-
-type PostPatternData struct {
-	PrePatternData
-	FileName                 string
-	FileNameWithoutExtension string
-	FullPath                 string
-}
-
-func createPostPatternData(fullPath string, prePatternData PrePatternData) PostPatternData {
-	fileName := filepath.Base(fullPath)
-	fileNameWithoutExt := fileName[:len(fileName)-len(filepath.Ext(fileName))]
-	return PostPatternData{
-		FullPath:                 fullPath,
-		FileName:                 fileName,
-		FileNameWithoutExtension: fileNameWithoutExt,
-		PrePatternData:           prePatternData,
-	}
-}
+package main

+

+import (

+	"path/filepath"

+	"time"

+)

+

+type PrePatternData struct {

+	ProjectName                            string

+	Year, Month, Day, Hour, Minute, Second string

+	YYYY_MM_DD 						   string

+	YYYY_MM_DD_HH_MM_SS 				   string

+	Extras                                 map[string]string

+}

+

+type PostPatternData struct {

+	PrePatternData

+	FileName                 string

+	FileNameWithoutExtension string

+	FullPath                 string

+}

+

+func createPrePatternData(now time.Time, projectName string, extras map[string]string) PrePatternData {

+	prePatternData := PrePatternData{

+		Year:        now.Format("2006"),

+		Month:       now.Format("01"),

+		Day:         now.Format("02"),

+		Hour:        now.Format("15"),

+		Minute:      now.Format("04"),

+		Second:      now.Format("05"),

+		YYYY_MM_DD:  now.Format("2006-01-02"),

+		YYYY_MM_DD_HH_MM_SS: now.Format("2006-01-02-15-04-05"),

+		ProjectName: projectName,

+		Extras:      extras,

+	}

+	return prePatternData

+}

+

+func createPostPatternData(fullPath string, prePatternData PrePatternData) PostPatternData {

+	fileName := filepath.Base(fullPath)

+	fileNameWithoutExt := fileName[:len(fileName)-len(filepath.Ext(fileName))]

+	return PostPatternData{

+		FullPath:                 fullPath,

+		FileName:                 fileName,

+		FileNameWithoutExtension: fileNameWithoutExt,

+		PrePatternData:           prePatternData,

+	}

+}

diff --git a/profile.go b/profile.go
index 0e20175..f8d4153 100644
--- a/profile.go
+++ b/profile.go
@@ -209,20 +209,6 @@ func shellCommandAndArgs(command string) (shell string, args []string) {
 	}
 }
 
-func createPrePatternData(now time.Time, projectName string, extras map[string]string) PrePatternData {
-	prePatternData := PrePatternData{
-		Year:        now.Format("2006"),
-		Month:       now.Format("01"),
-		Day:         now.Format("02"),
-		Hour:        now.Format("15"),
-		Minute:      now.Format("04"),
-		Second:      now.Format("05"),
-		ProjectName: projectName,
-		Extras:      extras,
-	}
-	return prePatternData
-}
-
 func createEntity(
 	now time.Time,
 	profile Profile,