Skip to content

Commit

Permalink
fix(cli): correct execution logic and improve messages
Browse files Browse the repository at this point in the history
  • Loading branch information
lewis-yeung authored and JanDeDobbeleer committed Aug 27, 2024
1 parent 48f633e commit e28d91b
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 75 deletions.
22 changes: 1 addition & 21 deletions src/cli/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cli
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"

Expand Down Expand Up @@ -50,7 +49,7 @@ You can do the following:
clear(env.CachePath())
case "edit":
cacheFilePath := filepath.Join(env.CachePath(), cache.FileName)
editFileWithEditor(cacheFilePath)
os.Exit(editFileWithEditor(cacheFilePath))
}
},
}
Expand All @@ -59,25 +58,6 @@ func init() {
RootCmd.AddCommand(getCache)
}

func editFileWithEditor(file string) {
editor := os.Getenv("EDITOR")

var args []string
if strings.Contains(editor, " ") {
splitted := strings.Split(editor, " ")
editor = splitted[0]
args = splitted[1:]
}

args = append(args, file)
cmd := exec.Command(editor, args...)

err := cmd.Run()
if err != nil {
fmt.Println(err.Error())
}
}

func clear(cachePath string) {
// get all files in the cache directory that start with omp.cache and delete them
files, err := os.ReadDir(cachePath)
Expand Down
14 changes: 11 additions & 3 deletions src/cli/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@ import (
"os"
"time"

"github.com/jandedobbeleer/oh-my-posh/src/runtime"

"github.com/spf13/cobra"
)

// configCmd represents the config command
var configCmd = &cobra.Command{
Use: "config [export|migrate|edit]",
Use: "config edit",
Short: "Interact with the config",
Long: `Interact with the config.
You can export, migrate or edit the config.`,
You can export, migrate or edit the config (via the editor specified in the environment variable "EDITOR").`,
ValidArgs: []string{
"export",
"migrate",
Expand All @@ -29,7 +31,13 @@ You can export, migrate or edit the config.`,
}
switch args[0] {
case "edit":
editFileWithEditor(os.Getenv("POSH_THEME"))
env := &runtime.Terminal{
CmdFlags: &runtime.Flags{
Config: configFlag,
},
}
env.ResolveConfigPath()
os.Exit(editFileWithEditor(env.CmdFlags.Config))
case "get":
// only here for backwards compatibility
fmt.Print(time.Now().UnixNano() / 1000000)
Expand Down
61 changes: 30 additions & 31 deletions src/cli/config_export.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"fmt"
"os"
"path/filepath"
"slices"
"strings"

"github.com/jandedobbeleer/oh-my-posh/src/config"
Expand All @@ -13,9 +12,7 @@ import (
"github.com/spf13/cobra"
)

var (
output string
)
var output string

// exportCmd represents the export command
var exportCmd = &cobra.Command{
Expand All @@ -27,15 +24,21 @@ You can choose to print the output to stdout, or export your config in the forma
Example usage:
> oh-my-posh config export --config ~/myconfig.omp.json
> oh-my-posh config export --config ~/myconfig.omp.json --format toml
Exports the ~/myconfig.omp.json config file and prints the result to stdout.
Exports the config file "~/myconfig.omp.json" in TOML format and prints the result to stdout.
> oh-my-posh config export --config ~/myconfig.omp.json --format toml
> oh-my-posh config export --output ~/new_config.omp.json
Exports the ~/myconfig.omp.json config file to toml and prints the result to stdout.`,
Exports the current config to "~/new_config.omp.json" (in JSON format).`,
Args: cobra.NoArgs,
Run: func(_ *cobra.Command, _ []string) {
if len(output) == 0 && len(format) == 0 {
// usage error
fmt.Println("neither output path nor export format is specified")
os.Exit(2)
}

env := &runtime.Terminal{
CmdFlags: &runtime.Flags{
Config: configFlag,
Expand All @@ -45,15 +48,25 @@ Exports the ~/myconfig.omp.json config file to toml and prints the result to std
defer env.Close()
cfg := config.Load(env)

if len(output) == 0 && len(format) == 0 {
// usage error
os.Exit(2)
validateExportFormat := func() {
format = strings.ToLower(format)
switch format {
case "json", "jsonc":
format = config.JSON
case "toml", "tml":
format = config.TOML
case "yaml", "yml":
format = config.YAML
default:
formats := []string{"json", "jsonc", "toml", "tml", "yaml", "yml"}
// usage error
fmt.Printf("export format must be one of these: %s\n", strings.Join(formats, ", "))
os.Exit(2)
}
}

formats := []string{"json", "jsonc", "toml", "tml", "yaml", "yml"}
if len(format) != 0 && !slices.Contains(formats, format) {
// usage error
os.Exit(2)
if len(format) != 0 {
validateExportFormat()
}

if len(output) == 0 {
Expand All @@ -65,29 +78,15 @@ Exports the ~/myconfig.omp.json config file to toml and prints the result to std

if len(format) == 0 {
format = strings.TrimPrefix(filepath.Ext(output), ".")
}

switch format {
case "json", "jsonc":
format = config.JSON
case "toml", "tml":
format = config.TOML
case "yaml", "yml":
format = config.YAML
default:
// data error
os.Exit(65)
validateExportFormat()
}

cfg.Write(format)
},
}

func cleanOutputPath(path string, env runtime.Environment) string {
if strings.HasPrefix(path, "~") {
path = strings.TrimPrefix(path, "~")
path = filepath.Join(env.Home(), path)
}
path = runtime.ReplaceTildePrefixWithHomeDir(env, path)

if !filepath.IsAbs(path) {
if absPath, err := filepath.Abs(path); err == nil {
Expand Down
34 changes: 34 additions & 0 deletions src/cli/edit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package cli

import (
"fmt"
"os"
"os/exec"
"strings"
)

func editFileWithEditor(file string) int {
editor := strings.TrimSpace(os.Getenv("EDITOR"))
if len(editor) == 0 {
fmt.Println(`no editor specified in the environment variable "EDITOR"`)
return 1
}

var args []string
if strings.Contains(editor, " ") {
strs := strings.Split(editor, " ")
editor = strs[0]
args = strs[1:]
}

args = append(args, file)
cmd := exec.Command(editor, args...)

err := cmd.Run()
if err != nil {
fmt.Println(err.Error())
return 1
}

return cmd.ProcessState.ExitCode()
}
1 change: 0 additions & 1 deletion src/cli/print.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ var printCmd = &cobra.Command{
Plain: plain,
Primary: args[0] == "primary",
Cleared: cleared,
Cached: cached,
NoExitCode: noStatus,
Column: column,
JobCount: jobCount,
Expand Down
1 change: 0 additions & 1 deletion src/runtime/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@ type Flags struct {
HasTransient bool
PromptCount int
Cleared bool
Cached bool
NoExitCode bool
Column int
JobCount int
Expand Down
37 changes: 22 additions & 15 deletions src/runtime/terminal.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,20 +74,18 @@ func (term *Terminal) Init() {
term.deviceCache = initCache(cache.FileName)
term.sessionCache = initCache(cache.SessionFileName)

term.resolveConfigPath()
term.ResolveConfigPath()

term.cmdCache = &cache.Command{
Commands: maps.NewConcurrent(),
}

term.tmplCache = &cache.Template{}

if !term.CmdFlags.Cached {
term.SetPromptCount()
}
term.SetPromptCount()
}

func (term *Terminal) resolveConfigPath() {
func (term *Terminal) ResolveConfigPath() {
defer term.Trace(time.Now())

// if the config flag is set, we'll use that over POSH_THEME
Expand Down Expand Up @@ -129,11 +127,7 @@ func (term *Terminal) resolveConfigPath() {
return
}

configFile := term.CmdFlags.Config
if strings.HasPrefix(configFile, "~") {
configFile = strings.TrimPrefix(configFile, "~")
configFile = filepath.Join(term.Home(), configFile)
}
configFile := ReplaceTildePrefixWithHomeDir(term, term.CmdFlags.Config)

abs, err := filepath.Abs(configFile)
if err != nil {
Expand Down Expand Up @@ -726,11 +720,14 @@ func dirMatchesOneOf(dir, home, goos string, regexes []string) bool {
}

for _, element := range regexes {
normalizedElement := strings.ReplaceAll(element, "\\\\", "/")
if strings.HasPrefix(normalizedElement, "~") {
normalizedElement = strings.Replace(normalizedElement, "~", home, 1)
normalized := strings.ReplaceAll(element, "\\\\", "/")
if strings.HasPrefix(normalized, "~") {
rem := normalized[1:]
if len(rem) == 0 || rem[0] == '/' {
normalized = home + rem
}
}
pattern := fmt.Sprintf("^%s$", normalizedElement)
pattern := fmt.Sprintf("^%s$", normalized)
if goos == WINDOWS || goos == DARWIN {
pattern = "(?i)" + pattern
}
Expand Down Expand Up @@ -843,9 +840,19 @@ func Base(env Environment, path string) string {
return path
}

func ReplaceTildePrefixWithHomeDir(env Environment, path string) string {
if !strings.HasPrefix(path, "~") {
return path
}
rem := path[1:]
if len(rem) == 0 || IsPathSeparator(env, rem[0]) {
return env.Home() + rem
}
return path
}

func ReplaceHomeDirPrefixWithTilde(env Environment, path string) string {
home := env.Home()
// match Home directory exactly
if !strings.HasPrefix(path, home) {
return path
}
Expand Down
6 changes: 3 additions & 3 deletions website/docs/configuration/segment.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ will not be rendered when in one of the excluded locations.
```

The strings specified in these properties are evaluated as [regular expressions][regex]. You
can use any valid regular expression construct, but the regular expression must match the entire directory
can use any valid regular expression construct, but the regular expression must match the **ENTIRE** directory
name. The following will match `/Users/posh/Projects/Foo` but not `/home/Users/posh/Projects/Foo`.

```json
Expand All @@ -165,8 +165,8 @@ You can also combine these properties:

- Oh My Posh will accept both `/` and `\` as path separators for a folder and will match regardless of which
is used by the current operating system.
- Because the strings are evaluated as regular expressions, if you want to use a `\` in a Windows
directory name, you need to specify it as `\\\\`.
- Because the strings are evaluated as regular expressions, if you want to use a backslash (`\`) in a Windows
directory name, you need to specify it as double backslashes, and if using JSON format you should escape it as `\\\\`.
- The character `~` at the start of a specified folder will match the user's home directory.
- The comparison is case-insensitive on Windows and macOS, but case-sensitive on other operating systems.

Expand Down

0 comments on commit e28d91b

Please sign in to comment.