1package configdir_test
2
3import (
4	"encoding/json"
5	"fmt"
6	"os"
7	"path/filepath"
8
9	"github.com/kirsle/configdir"
10)
11
12// Quick start example for a common use case of this module.
13func Example() {
14	// A common use case is to get a private config folder for your app to
15	// place its settings files into, that are specific to the local user.
16	configPath := configdir.LocalConfig("my-app")
17	err := configdir.MakePath(configPath) // Ensure it exists.
18	if err != nil {
19		panic(err)
20	}
21
22	// Deal with a JSON configuration file in that folder.
23	configFile := filepath.Join(configPath, "settings.json")
24	type AppSettings struct {
25		Username string `json:"username"`
26		Password string `json:"password"`
27	}
28	var settings AppSettings
29
30	// Does the file not exist?
31	if _, err = os.Stat(configFile); os.IsNotExist(err) {
32		// Create the new config file.
33		settings = AppSettings{"MyUser", "MyPassword"}
34		fh, err := os.Create(configFile)
35		if err != nil {
36			panic(err)
37		}
38		defer fh.Close()
39
40		encoder := json.NewEncoder(fh)
41		encoder.Encode(&settings)
42	} else {
43		// Load the existing file.
44		fh, err := os.Open(configFile)
45		if err != nil {
46			panic(err)
47		}
48		defer fh.Close()
49
50		decoder := json.NewDecoder(fh)
51		decoder.Decode(&settings)
52	}
53}
54
55// Example for getting a global system configuration path.
56func ExampleSystemConfig() {
57	// Get all of the global system configuration paths.
58	//
59	// On Linux or BSD this might be []string{"/etc/xdg"} or the split
60	// version of $XDG_CONFIG_DIRS.
61	//
62	// On macOS or Windows this will likely return a slice with only one entry
63	// that points to the global config path; see the README.md for details.
64	paths := configdir.SystemConfig()
65	fmt.Printf("Global system config paths: %v\n", paths)
66
67	// Or you can get a version of the path suffixed with a vendor folder.
68	vendor := configdir.SystemConfig("acme")
69	fmt.Printf("Vendor-specific config paths: %v\n", vendor)
70
71	// Or you can use multiple path suffixes to group configs in a
72	// `vendor/application` namespace. You can use as many path
73	// components as you like.
74	app := configdir.SystemConfig("acme", "sprockets")
75	fmt.Printf("Vendor/app specific config paths: %v\n", app)
76}
77
78// Example for getting a user-specific configuration path.
79func ExampleLocalConfig() {
80	// Get the default root of the local configuration path.
81	//
82	// On Linux or BSD this might be "$HOME/.config", or on Windows this might
83	// be "C:\\Users\\$USER\\AppData\\Roaming"
84	path := configdir.LocalConfig()
85	fmt.Printf("Local user config path: %s\n", path)
86
87	// Or you can get a local config path with a vendor suffix, like
88	// "$HOME/.config/acme" on Linux.
89	vendor := configdir.LocalConfig("acme")
90	fmt.Printf("Vendor-specific local config path: %s\n", vendor)
91
92	// Or you can use multiple path suffixes to group configs in a
93	// `vendor/application` namespace. You can use as many path
94	// components as you like.
95	app := configdir.LocalConfig("acme", "sprockets")
96	fmt.Printf("Vendor/app specific local config path: %s\n", app)
97}
98
99// Example for getting a user-specific cache folder.
100func ExampleLocalCache() {
101	// Get the default root of the local cache folder.
102	//
103	// On Linux or BSD this might be "$HOME/.cache", or on Windows this might
104	// be "C:\\Users\\$USER\\AppData\\Local"
105	path := configdir.LocalCache()
106	fmt.Printf("Local user cache path: %s\n", path)
107
108	// Or you can get a local cache path with a vendor suffix, like
109	// "$HOME/.cache/acme" on Linux.
110	vendor := configdir.LocalCache("acme")
111	fmt.Printf("Vendor-specific local cache path: %s\n", vendor)
112
113	// Or you can use multiple path suffixes to group caches in a
114	// `vendor/application` namespace. You can use as many path
115	// components as you like.
116	app := configdir.LocalCache("acme", "sprockets")
117	fmt.Printf("Vendor/app specific local cache path: %s\n", app)
118}
119
120// Example for automatically creating config directories.
121func ExampleMakePath() {
122	// The MakePath() function can accept the output of any of the folder
123	// getting functions and ensure that their path exists.
124
125	// Create a local user configuration folder under an app prefix.
126	// On Linux this may result in `$HOME/.config/my-cool-app` existing as
127	// a directory, depending on the value of `$XDG_CONFIG_HOME`.
128	err := configdir.MakePath(configdir.LocalConfig("my-cool-app"))
129	if err != nil {
130		panic(err)
131	}
132
133	// Create a cache folder under a namespace.
134	err = configdir.MakePath(configdir.LocalCache("acme", "sprockets", "client"))
135	if err != nil {
136		panic(err)
137	}
138
139	// In the case of global system configuration, which may return more than
140	// one path (especially on Linux/BSD that uses the XDG Base Directory Spec),
141	// it will attempt to create the directories only under the *first* path.
142	//
143	// For example, if $XDG_CONFIG_DIRS="/etc/xdg:/opt/config" this will try
144	// to create the config dir only in "/etc/xdg/acme/sprockets" and not try
145	// to create any folders under "/opt/config".
146	err = configdir.MakePath(configdir.SystemConfig("acme", "sprockets")...)
147	if err != nil {
148		panic(err)
149	}
150}
151
152// Example for recalculating what the directories should be.
153func ExampleRefresh() {
154	// On your program's initialization, this module decides which paths to
155	// use for global, local and cache folders, based on environment variables
156	// and falling back on defaults.
157	//
158	// In case the environment variables change throughout the life of your
159	// program, for example if you re-assigned $XDG_CONFIG_HOME, you can call
160	// the Refresh() function to re-calculate the paths to reflect the new
161	// environment.
162	configdir.Refresh()
163}
164