From e59e42a6c235f912814ad875b1f4107a66b57ab6 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 26 May 2023 22:42:07 +0530 Subject: [PATCH] simplify API of utils.Once --- kittens/diff/highlight.go | 4 ++-- kittens/diff/mouse.go | 4 ++-- kittens/diff/patch.go | 8 ++++---- kittens/hints/marks.go | 8 ++++---- kittens/hyperlinked_grep/main.go | 4 ++-- kittens/ssh/data.go | 4 ++-- kittens/ssh/utils.go | 16 ++++++++-------- tools/config/utils.go | 8 ++++---- tools/themes/collection.go | 4 ++-- tools/tui/tmux.go | 8 ++++---- tools/utils/hostname.go | 4 ++-- tools/utils/images/loading.go | 4 ++-- tools/utils/mimetypes.go | 4 ++-- tools/utils/once.go | 10 +++++++--- tools/utils/once_test.go | 4 ++-- tools/utils/paths.go | 16 ++++++++-------- tools/utils/which.go | 4 ++-- 17 files changed, 59 insertions(+), 55 deletions(-) diff --git a/kittens/diff/highlight.go b/kittens/diff/highlight.go index 9698edcab..cd79d4fa0 100644 --- a/kittens/diff/highlight.go +++ b/kittens/diff/highlight.go @@ -22,7 +22,7 @@ var _ = fmt.Print var _ = os.WriteFile var ErrNoLexer = errors.New("No lexer available for this format") -var DefaultStyle = (&utils.Once[*chroma.Style]{Run: func() *chroma.Style { +var DefaultStyle = utils.Once(func() *chroma.Style { // Default style generated by python style.py default pygments.styles.default.DefaultStyle // with https://raw.githubusercontent.com/alecthomas/chroma/master/_tools/style.py return styles.Register(chroma.MustNewStyle("default", chroma.StyleEntries{ @@ -67,7 +67,7 @@ var DefaultStyle = (&utils.Once[*chroma.Style]{Run: func() *chroma.Style { chroma.Error: "border:#FF0000", chroma.Background: " bg:#f8f8f8", })) -}}).Get +}) // Clear the background colour. func clear_background(style *chroma.Style) *chroma.Style { diff --git a/kittens/diff/mouse.go b/kittens/diff/mouse.go index 29c269c00..f3c328674 100644 --- a/kittens/diff/mouse.go +++ b/kittens/diff/mouse.go @@ -42,9 +42,9 @@ func read_relevant_kitty_opts(path string) KittyOpts { return ans } -var RelevantKittyOpts = (&utils.Once[KittyOpts]{Run: func() KittyOpts { +var RelevantKittyOpts = utils.Once(func() KittyOpts { return read_relevant_kitty_opts(filepath.Join(utils.ConfigDir(), "kitty.conf")) -}}).Get +}) func (self *Handler) handle_wheel_event(up bool) { amt := RelevantKittyOpts().Wheel_scroll_multiplier diff --git a/kittens/diff/patch.go b/kittens/diff/patch.go index ed8cdec36..cb9e699f2 100644 --- a/kittens/diff/patch.go +++ b/kittens/diff/patch.go @@ -22,13 +22,13 @@ const DIFF_DIFF = `diff -p -U _CONTEXT_ --` var diff_cmd []string -var GitExe = (&utils.Once[string]{Run: func() string { +var GitExe = utils.Once(func() string { return utils.FindExe("git") -}}).Get +}) -var DiffExe = (&utils.Once[string]{Run: func() string { +var DiffExe = utils.Once(func() string { return utils.FindExe("diff") -}}).Get +}) func find_differ() { if GitExe() != "git" && exec.Command(GitExe(), "--help").Run() == nil { diff --git a/kittens/hints/marks.go b/kittens/hints/marks.go index 72ae99eaf..eef54db47 100644 --- a/kittens/hints/marks.go +++ b/kittens/hints/marks.go @@ -162,7 +162,7 @@ func linenum_group_processor(gd map[string]string) { gd[`path`] = utils.Expanduser(gd[`path`]) } -var PostProcessorMap = (&utils.Once[map[string]PostProcessorFunc]{Run: func() map[string]PostProcessorFunc { +var PostProcessorMap = utils.Once(func() map[string]PostProcessorFunc { return map[string]PostProcessorFunc{ "url": func(text string, s, e int) (int, int) { if s > 4 && text[s-5:s] == "link:" { // asciidoc URLs @@ -200,7 +200,7 @@ var PostProcessorMap = (&utils.Once[map[string]PostProcessorFunc]{Run: func() ma return s, e }, } -}}).Get +}) type KittyOpts struct { Url_prefixes *utils.Set[string] @@ -226,9 +226,9 @@ func read_relevant_kitty_opts(path string) KittyOpts { return ans } -var RelevantKittyOpts = (&utils.Once[KittyOpts]{Run: func() KittyOpts { +var RelevantKittyOpts = utils.Once(func() KittyOpts { return read_relevant_kitty_opts(filepath.Join(utils.ConfigDir(), "kitty.conf")) -}}).Get +}) func functions_for(opts *Options) (pattern string, post_processors []PostProcessorFunc, group_processors []GroupProcessorFunc) { switch opts.Type { diff --git a/kittens/hyperlinked_grep/main.go b/kittens/hyperlinked_grep/main.go index bb8d5b95d..359207560 100644 --- a/kittens/hyperlinked_grep/main.go +++ b/kittens/hyperlinked_grep/main.go @@ -22,9 +22,9 @@ import ( var _ = fmt.Print -var RgExe = (&utils.Once[string]{Run: func() string { +var RgExe = utils.Once(func() string { return utils.FindExe("rg") -}}).Get +}) func get_options_for_rg() (expecting_args map[string]bool, alias_map map[string]string, err error) { var raw []byte diff --git a/kittens/ssh/data.go b/kittens/ssh/data.go index 4b224f9b1..77d17f3ae 100644 --- a/kittens/ssh/data.go +++ b/kittens/ssh/data.go @@ -25,7 +25,7 @@ type Entry struct { type Container map[string]Entry -var Data = (&utils.Once[Container]{Run: func() Container { +var Data = utils.Once(func() Container { tr := tar.NewReader(utils.ReaderForCompressedEmbeddedData(embedded_data)) ans := make(Container, 64) for { @@ -43,7 +43,7 @@ var Data = (&utils.Once[Container]{Run: func() Container { ans[hdr.Name] = Entry{hdr, data} } return ans -}}).Get +}) func (self Container) files_matching(prefix string, exclude_patterns ...string) []string { ans := make([]string, 0, len(self)) diff --git a/kittens/ssh/utils.go b/kittens/ssh/utils.go index 972417de7..358c9805a 100644 --- a/kittens/ssh/utils.go +++ b/kittens/ssh/utils.go @@ -17,11 +17,11 @@ import ( var _ = fmt.Print -var SSHExe = (&utils.Once[string]{Run: func() string { +var SSHExe = utils.Once(func() string { return utils.FindExe("ssh") -}}).Get +}) -var SSHOptions = (&utils.Once[map[string]string]{Run: func() (ssh_options map[string]string) { +var SSHOptions = utils.Once(func() (ssh_options map[string]string) { defer func() { if ssh_options == nil { ssh_options = map[string]string{ @@ -80,7 +80,7 @@ var SSHOptions = (&utils.Once[map[string]string]{Run: func() (ssh_options map[st } } return -}}).Get +}) func GetSSHCLI() (boolean_ssh_args *utils.Set[string], other_ssh_args *utils.Set[string]) { other_ssh_args, boolean_ssh_args = utils.NewSet[string](32), utils.NewSet[string](32) @@ -201,7 +201,7 @@ func (self SSHVersion) SupportsAskpassRequire() bool { return self.Major > 8 || (self.Major == 8 && self.Minor >= 4) } -var GetSSHVersion = (&utils.Once[SSHVersion]{Run: func() SSHVersion { +var GetSSHVersion = utils.Once(func() SSHVersion { b, err := exec.Command(SSHExe(), "-V").CombinedOutput() if err != nil { return SSHVersion{} @@ -213,7 +213,7 @@ var GetSSHVersion = (&utils.Once[SSHVersion]{Run: func() SSHVersion { return SSHVersion{Major: maj, Minor: min} } return SSHVersion{} -}}).Get +}) type KittyOpts struct { Term, Shell_integration string @@ -235,6 +235,6 @@ func read_relevant_kitty_opts(path string) KittyOpts { return ans } -var RelevantKittyOpts = (&utils.Once[KittyOpts]{Run: func() KittyOpts { +var RelevantKittyOpts = utils.Once(func() KittyOpts { return read_relevant_kitty_opts(filepath.Join(utils.ConfigDir(), "kitty.conf")) -}}).Get +}) diff --git a/tools/config/utils.go b/tools/config/utils.go index 9cabf8baa..dd1fc937f 100644 --- a/tools/config/utils.go +++ b/tools/config/utils.go @@ -189,7 +189,7 @@ func StringLiteral(val string) (string, error) { return ans.String(), nil } -var ModMap = (&utils.Once[map[string]string]{Run: func() map[string]string { +var ModMap = utils.Once(func() map[string]string { return map[string]string{ "shift": "shift", "⇧": "shift", @@ -209,11 +209,11 @@ var ModMap = (&utils.Once[map[string]string]{Run: func() map[string]string { "num_lock": "num_lock", "caps_lock": "caps_lock", } -}}).Get +}) -var ShortcutSpecPat = (&utils.Once[*regexp.Regexp]{Run: func() *regexp.Regexp { +var ShortcutSpecPat = utils.Once(func() *regexp.Regexp { return regexp.MustCompile(`([^+])>`) -}}).Get +}) func NormalizeShortcut(spec string) string { parts := strings.Split(strings.ToLower(spec), "+") diff --git a/tools/themes/collection.go b/tools/themes/collection.go index 7e7ea80d3..dc16ed28c 100644 --- a/tools/themes/collection.go +++ b/tools/themes/collection.go @@ -780,9 +780,9 @@ func (self *Themes) Copy() *Themes { return ans } -var camel_case_pat = (&utils.Once[*regexp.Regexp]{Run: func() *regexp.Regexp { +var camel_case_pat = utils.Once(func() *regexp.Regexp { return regexp.MustCompile(`([a-z])([A-Z])`) -}}).Get +}) func ThemeNameFromFileName(fname string) string { fname = fname[:len(fname)-len(path.Ext(fname))] diff --git a/tools/tui/tmux.go b/tools/tui/tmux.go index b279cf805..f3d9a21c9 100644 --- a/tools/tui/tmux.go +++ b/tools/tui/tmux.go @@ -20,9 +20,9 @@ import ( var _ = fmt.Print -var TmuxExe = (&utils.Once[string]{Run: func() string { +var TmuxExe = utils.Once(func() string { return utils.FindExe("tmux") -}}).Get +}) func tmux_socket_address() (socket string) { socket = os.Getenv("TMUX") @@ -55,7 +55,7 @@ func tmux_socket_address() (socket string) { return socket } -var TmuxSocketAddress = (&utils.Once[string]{Run: tmux_socket_address}).Get +var TmuxSocketAddress = utils.Once(tmux_socket_address) func tmux_command(args ...string) (c *exec.Cmd, stderr *strings.Builder) { c = exec.Command(TmuxExe(), args...) @@ -100,4 +100,4 @@ func tmux_allow_passthrough() error { } } -var TmuxAllowPassthrough = (&utils.Once[error]{Run: tmux_allow_passthrough}).Get +var TmuxAllowPassthrough = utils.Once(tmux_allow_passthrough) diff --git a/tools/utils/hostname.go b/tools/utils/hostname.go index a7e81b9a0..5e1effe39 100644 --- a/tools/utils/hostname.go +++ b/tools/utils/hostname.go @@ -11,10 +11,10 @@ var _ = fmt.Print var hostname string = "*" -var Hostname = (&Once[string]{Run: func() string { +var Hostname = Once(func() string { h, err := os.Hostname() if err == nil { return h } return "" -}}).Get +}) diff --git a/tools/utils/images/loading.go b/tools/utils/images/loading.go index 229950144..9289abc67 100644 --- a/tools/utils/images/loading.go +++ b/tools/utils/images/loading.go @@ -264,9 +264,9 @@ func OpenNativeImageFromReader(f io.ReadSeeker) (ans *ImageData, err error) { return } -var MagickExe = (&utils.Once[string]{Run: func() string { +var MagickExe = utils.Once(func() string { return utils.FindExe("magick") -}}).Get +}) func RunMagick(path string, cmd []string) ([]byte, error) { if MagickExe() != "magick" { diff --git a/tools/utils/mimetypes.go b/tools/utils/mimetypes.go index d1027bcca..c742d9d65 100644 --- a/tools/utils/mimetypes.go +++ b/tools/utils/mimetypes.go @@ -44,7 +44,7 @@ func load_mime_file(filename string, mime_map map[string]string) error { return nil } -var UserMimeMap = (&Once[map[string]string]{Run: func() map[string]string { +var UserMimeMap = Once(func() map[string]string { conf_path := filepath.Join(ConfigDir(), "mime.types") ans := make(map[string]string, 32) err := load_mime_file(conf_path, ans) @@ -52,7 +52,7 @@ var UserMimeMap = (&Once[map[string]string]{Run: func() map[string]string { fmt.Fprintln(os.Stderr, "Failed to parse", conf_path, "for MIME types with error:", err) } return ans -}}).Get +}) func is_rcfile(path string) bool { name := filepath.Base(path) diff --git a/tools/utils/once.go b/tools/utils/once.go index 03734448d..822a8ab24 100644 --- a/tools/utils/once.go +++ b/tools/utils/once.go @@ -10,7 +10,7 @@ import ( var _ = fmt.Print -type Once[T any] struct { +type once[T any] struct { done uint32 mutex sync.Mutex cached_val T @@ -18,14 +18,14 @@ type Once[T any] struct { Run func() T } -func (self *Once[T]) Get() T { +func (self *once[T]) Get() T { if atomic.LoadUint32(&self.done) == 0 { self.do_slow() } return self.cached_val } -func (self *Once[T]) do_slow() { +func (self *once[T]) do_slow() { self.mutex.Lock() defer self.mutex.Unlock() if atomic.LoadUint32(&self.done) == 0 { @@ -33,3 +33,7 @@ func (self *Once[T]) do_slow() { self.cached_val = self.Run() } } + +func Once[T any](f func() T) func() T { + return (&once[T]{Run: f}).Get +} diff --git a/tools/utils/once_test.go b/tools/utils/once_test.go index c748dd16a..63518090d 100644 --- a/tools/utils/once_test.go +++ b/tools/utils/once_test.go @@ -11,10 +11,10 @@ var _ = fmt.Print func TestOnce(t *testing.T) { num := 0 - var G = (&Once[string]{Run: func() string { + var G = Once(func() string { num++ return fmt.Sprintf("%d", num) - }}).Get + }) G() G() G() diff --git a/tools/utils/paths.go b/tools/utils/paths.go index d4695a61b..e70402d5e 100644 --- a/tools/utils/paths.go +++ b/tools/utils/paths.go @@ -62,7 +62,7 @@ func Abspath(path string) string { return path } -var KittyExe = (&Once[string]{Run: func() string { +var KittyExe = Once(func() string { exe, err := os.Executable() if err == nil { ans := filepath.Join(filepath.Dir(exe), "kitty") @@ -71,7 +71,7 @@ var KittyExe = (&Once[string]{Run: func() string { } } return os.Getenv("KITTY_PATH_TO_KITTY_EXE") -}}).Get +}) func ConfigDirForName(name string) (config_dir string) { if kcd := os.Getenv("KITTY_CONFIG_DIRECTORY"); kcd != "" { @@ -117,11 +117,11 @@ func ConfigDirForName(name string) (config_dir string) { return } -var ConfigDir = (&Once[string]{Run: func() (config_dir string) { +var ConfigDir = Once(func() (config_dir string) { return ConfigDirForName("kitty.conf") -}}).Get +}) -var CacheDir = (&Once[string]{Run: func() (cache_dir string) { +var CacheDir = Once(func() (cache_dir string) { candidate := "" if edir := os.Getenv("KITTY_CACHE_DIRECTORY"); edir != "" { candidate = Abspath(Expanduser(edir)) @@ -136,7 +136,7 @@ var CacheDir = (&Once[string]{Run: func() (cache_dir string) { } os.MkdirAll(candidate, 0o755) return candidate -}}).Get +}) func macos_user_cache_dir() string { // Sadly Go does not provide confstr() so we use this hack. @@ -176,7 +176,7 @@ func macos_user_cache_dir() string { return "" } -var RuntimeDir = (&Once[string]{Run: func() (runtime_dir string) { +var RuntimeDir = Once(func() (runtime_dir string) { var candidate string if q := os.Getenv("KITTY_RUNTIME_DIRECTORY"); q != "" { candidate = q @@ -199,7 +199,7 @@ var RuntimeDir = (&Once[string]{Run: func() (runtime_dir string) { os.Chmod(candidate, 0o700) } return candidate -}}).Get +}) type Walk_callback func(path, abspath string, d fs.DirEntry, err error) error diff --git a/tools/utils/which.go b/tools/utils/which.go index fcc0e7858..c5f015ffa 100644 --- a/tools/utils/which.go +++ b/tools/utils/which.go @@ -13,7 +13,7 @@ import ( var _ = fmt.Print -var DefaultExeSearchPaths = (&Once[[]string]{Run: func() []string { +var DefaultExeSearchPaths = Once(func() []string { candidates := [...]string{"/usr/local/bin", "/opt/bin", "/opt/homebrew/bin", "/usr/bin", "/bin", "/usr/sbin", "/sbin"} ans := make([]string, 0, len(candidates)) for _, x := range candidates { @@ -22,7 +22,7 @@ var DefaultExeSearchPaths = (&Once[[]string]{Run: func() []string { } } return ans -}}).Get +}) func Which(cmd string, paths ...string) string { if strings.Contains(cmd, string(os.PathSeparator)) {