mirror of
https://github.com/JanDeDobbeleer/oh-my-posh.git
synced 2024-11-09 20:44:03 -08:00
Merge branch 'main' into faq
This commit is contained in:
commit
aa68c6c8b6
|
@ -32,3 +32,17 @@ trim_trailing_whitespace = false
|
|||
[*.{ps1,psd1,psm1}]
|
||||
indent_size = 4
|
||||
charset = utf-8-bom
|
||||
|
||||
; Lua
|
||||
[*.lua]
|
||||
line_space_after_comment = max(2)
|
||||
line_space_after_do_statement = max(2)
|
||||
line_space_after_expression_statement = max(2)
|
||||
line_space_after_for_statement = max(2)
|
||||
line_space_after_function_statement = fixed(2)
|
||||
line_space_after_if_statement = max(2)
|
||||
line_space_after_local_or_assign_statement = max(2)
|
||||
line_space_after_repeat_statement = max(2)
|
||||
line_space_after_while_statement = max(2)
|
||||
max_line_length = unset
|
||||
quote_style = single
|
||||
|
|
2
.github/workflows/docs.yml
vendored
2
.github/workflows/docs.yml
vendored
|
@ -44,7 +44,7 @@ jobs:
|
|||
- name: Set default Kubernetes namespace
|
||||
run: |
|
||||
kubectl config set-context posh --namespace demo
|
||||
- uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a
|
||||
- uses: azure/login@a65d910e8af852a8061c627c456678983e180302
|
||||
with:
|
||||
creds: ${{ secrets.AZURE_CREDENTIALS }}
|
||||
- name: Build oh-my-posh 🔧
|
||||
|
|
6
src/cache/cache.go
vendored
6
src/cache/cache.go
vendored
|
@ -10,7 +10,7 @@ import (
|
|||
)
|
||||
|
||||
type Cache interface {
|
||||
Init(home string)
|
||||
Init(filePath string, persist bool)
|
||||
Close()
|
||||
// Gets the value for a given key.
|
||||
// Returns the value and a boolean indicating if the key was found.
|
||||
|
@ -27,9 +27,9 @@ const (
|
|||
FileName = "omp.cache"
|
||||
)
|
||||
|
||||
var SessionFileName = fmt.Sprintf("%s.%s", FileName, pid())
|
||||
var SessionFileName = fmt.Sprintf("%s.%s", FileName, sessionID())
|
||||
|
||||
func pid() string {
|
||||
func sessionID() string {
|
||||
pid := os.Getenv("POSH_PID")
|
||||
if len(pid) == 0 {
|
||||
log.Debug("POSH_PID not set, using process pid")
|
||||
|
|
8
src/cache/file.go
vendored
8
src/cache/file.go
vendored
|
@ -13,13 +13,15 @@ type File struct {
|
|||
cache *maps.Concurrent
|
||||
cacheFilePath string
|
||||
dirty bool
|
||||
persist bool
|
||||
}
|
||||
|
||||
func (fc *File) Init(cacheFilePath string) {
|
||||
func (fc *File) Init(cacheFilePath string, persist bool) {
|
||||
defer log.Trace(time.Now(), cacheFilePath)
|
||||
|
||||
fc.cache = maps.NewConcurrent()
|
||||
fc.cacheFilePath = cacheFilePath
|
||||
fc.persist = persist
|
||||
|
||||
log.Debug("loading cache file:", fc.cacheFilePath)
|
||||
|
||||
|
@ -47,14 +49,14 @@ func (fc *File) Init(cacheFilePath string) {
|
|||
}
|
||||
|
||||
func (fc *File) Close() {
|
||||
if !fc.dirty {
|
||||
if !fc.persist || !fc.dirty {
|
||||
return
|
||||
}
|
||||
|
||||
cache := fc.cache.ToSimple()
|
||||
|
||||
if dump, err := json.MarshalIndent(cache, "", " "); err == nil {
|
||||
_ = os.WriteFile(fc.cacheFilePath, dump, 0644)
|
||||
_ = os.WriteFile(fc.cacheFilePath, dump, 0o644)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
14
src/cache/mock/cache.go
vendored
14
src/cache/mock/cache.go
vendored
|
@ -2,17 +2,18 @@ package mock
|
|||
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
|
||||
// Cache is an autogenerated mock type for the cache type
|
||||
type Cache struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// close provides a mock function with given fields:
|
||||
func (_m *Cache) Init(filePath string, persist bool) {
|
||||
_m.Called(filePath, persist)
|
||||
}
|
||||
|
||||
func (_m *Cache) Close() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// get provides a mock function with given fields: key
|
||||
func (_m *Cache) Get(key string) (string, bool) {
|
||||
ret := _m.Called(key)
|
||||
|
||||
|
@ -33,17 +34,10 @@ func (_m *Cache) Get(key string) (string, bool) {
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// init provides a mock function with given fields: home
|
||||
func (_m *Cache) Init(home string) {
|
||||
_m.Called(home)
|
||||
}
|
||||
|
||||
// set provides a mock function with given fields: key, value, ttl
|
||||
func (_m *Cache) Set(key, value string, ttl int) {
|
||||
_m.Called(key, value, ttl)
|
||||
}
|
||||
|
||||
// delete provides a mock function with given fields: key
|
||||
func (_m *Cache) Delete(key string) {
|
||||
_m.Called(key)
|
||||
}
|
||||
|
|
110
src/cli/debug.go
110
src/cli/debug.go
|
@ -15,56 +15,68 @@ import (
|
|||
)
|
||||
|
||||
// debugCmd represents the prompt command
|
||||
var debugCmd = &cobra.Command{
|
||||
Use: "debug [bash|zsh|fish|powershell|pwsh|cmd|nu|tcsh|elvish|xonsh]",
|
||||
Short: "Print the prompt in debug mode",
|
||||
Long: "Print the prompt in debug mode.",
|
||||
ValidArgs: supportedShells,
|
||||
Args: NoArgsOrOneValidArg,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
startTime := time.Now()
|
||||
|
||||
if len(args) == 0 {
|
||||
_ = cmd.Help()
|
||||
return
|
||||
}
|
||||
|
||||
env := &runtime.Terminal{
|
||||
CmdFlags: &runtime.Flags{
|
||||
Config: configFlag,
|
||||
Debug: true,
|
||||
PWD: pwd,
|
||||
Shell: args[0],
|
||||
Plain: plain,
|
||||
},
|
||||
}
|
||||
|
||||
env.Init()
|
||||
defer env.Close()
|
||||
|
||||
cfg := config.Load(env)
|
||||
|
||||
// add variables to the environment
|
||||
env.Var = cfg.Var
|
||||
|
||||
terminal.Init(shell.GENERIC)
|
||||
terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate(env)
|
||||
terminal.Colors = cfg.MakeColors()
|
||||
terminal.Plain = plain
|
||||
|
||||
eng := &prompt.Engine{
|
||||
Config: cfg,
|
||||
Env: env,
|
||||
Plain: plain,
|
||||
}
|
||||
|
||||
fmt.Print(eng.PrintDebug(startTime, build.Version))
|
||||
},
|
||||
}
|
||||
var debugCmd = createDebugCmd()
|
||||
|
||||
func init() {
|
||||
debugCmd.Flags().StringVar(&pwd, "pwd", "", "current working directory")
|
||||
debugCmd.Flags().StringVar(&shellName, "shell", "", "the shell to print for")
|
||||
debugCmd.Flags().BoolVarP(&plain, "plain", "p", false, "plain text output (no ANSI)")
|
||||
RootCmd.AddCommand(debugCmd)
|
||||
}
|
||||
|
||||
func createDebugCmd() *cobra.Command {
|
||||
debugCmd := &cobra.Command{
|
||||
Use: "debug [bash|zsh|fish|powershell|pwsh|cmd|nu|tcsh|elvish|xonsh]",
|
||||
Short: "Print the prompt in debug mode",
|
||||
Long: "Print the prompt in debug mode.",
|
||||
ValidArgs: supportedShells,
|
||||
Args: NoArgsOrOneValidArg,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
startTime := time.Now()
|
||||
|
||||
if len(args) == 0 {
|
||||
_ = cmd.Help()
|
||||
return
|
||||
}
|
||||
|
||||
env := &runtime.Terminal{
|
||||
CmdFlags: &runtime.Flags{
|
||||
Config: configFlag,
|
||||
Debug: true,
|
||||
PWD: pwd,
|
||||
Shell: args[0],
|
||||
Plain: plain,
|
||||
},
|
||||
}
|
||||
|
||||
env.Init()
|
||||
defer env.Close()
|
||||
|
||||
cfg := config.Load(env)
|
||||
|
||||
// add variables to the environment
|
||||
env.Var = cfg.Var
|
||||
|
||||
terminal.Init(shell.GENERIC)
|
||||
terminal.BackgroundColor = cfg.TerminalBackground.ResolveTemplate(env)
|
||||
terminal.Colors = cfg.MakeColors()
|
||||
terminal.Plain = plain
|
||||
|
||||
eng := &prompt.Engine{
|
||||
Config: cfg,
|
||||
Env: env,
|
||||
Plain: plain,
|
||||
}
|
||||
|
||||
fmt.Print(eng.PrintDebug(startTime, build.Version))
|
||||
},
|
||||
}
|
||||
|
||||
debugCmd.Flags().StringVar(&pwd, "pwd", "", "current working directory")
|
||||
debugCmd.Flags().BoolVarP(&plain, "plain", "p", false, "plain text output (no ANSI)")
|
||||
|
||||
// Deprecated flags, should be kept to avoid breaking CLI integration.
|
||||
debugCmd.Flags().StringVar(&shellName, "shell", "", "the shell to print for")
|
||||
|
||||
// Hide flags that are deprecated or for internal use only.
|
||||
_ = debugCmd.Flags().MarkHidden("shell")
|
||||
|
||||
return debugCmd
|
||||
}
|
||||
|
|
|
@ -44,11 +44,14 @@ func init() {
|
|||
func toggleFeature(cmd *cobra.Command, feature string, enable bool) {
|
||||
env := &runtime.Terminal{
|
||||
CmdFlags: &runtime.Flags{
|
||||
Shell: shellName,
|
||||
Shell: shellName,
|
||||
SaveCache: true,
|
||||
},
|
||||
}
|
||||
|
||||
env.Init()
|
||||
defer env.Close()
|
||||
|
||||
switch feature {
|
||||
case "notice":
|
||||
if enable {
|
||||
|
|
|
@ -36,7 +36,12 @@ This command is used to install fonts and configure the font in your terminal.
|
|||
fontName = args[1]
|
||||
}
|
||||
|
||||
env := &runtime.Terminal{}
|
||||
env := &runtime.Terminal{
|
||||
CmdFlags: &runtime.Flags{
|
||||
SaveCache: true,
|
||||
},
|
||||
}
|
||||
|
||||
env.Init()
|
||||
defer env.Close()
|
||||
|
||||
|
|
|
@ -30,7 +30,15 @@ var (
|
|||
"xonsh",
|
||||
}
|
||||
|
||||
initCmd = &cobra.Command{
|
||||
initCmd = createInitCmd()
|
||||
)
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(initCmd)
|
||||
}
|
||||
|
||||
func createInitCmd() *cobra.Command {
|
||||
initCmd := &cobra.Command{
|
||||
Use: "init [bash|zsh|fish|powershell|pwsh|cmd|nu|tcsh|elvish|xonsh]",
|
||||
Short: "Initialize your shell and config",
|
||||
Long: `Initialize your shell and config.
|
||||
|
@ -46,15 +54,20 @@ See the documentation to initialize your shell: https://ohmyposh.dev/docs/instal
|
|||
runInit(args[0])
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
initCmd.Flags().BoolVarP(&printOutput, "print", "p", false, "print the init script")
|
||||
initCmd.Flags().BoolVarP(&strict, "strict", "s", false, "run in strict mode")
|
||||
initCmd.Flags().BoolVarP(&manual, "manual", "m", false, "enable/disable manual mode")
|
||||
initCmd.Flags().BoolVar(&debug, "debug", false, "enable/disable debug mode")
|
||||
|
||||
// Deprecated flags, should be kept to avoid breaking CLI integration.
|
||||
initCmd.Flags().BoolVarP(&manual, "manual", "m", false, "enable/disable manual mode")
|
||||
|
||||
// Hide flags that are deprecated or for internal use only.
|
||||
_ = initCmd.Flags().MarkHidden("manual")
|
||||
|
||||
_ = initCmd.MarkPersistentFlagRequired("config")
|
||||
RootCmd.AddCommand(initCmd)
|
||||
|
||||
return initCmd
|
||||
}
|
||||
|
||||
func runInit(shellName string) {
|
||||
|
@ -68,7 +81,6 @@ func runInit(shellName string) {
|
|||
Shell: shellName,
|
||||
Config: configFlag,
|
||||
Strict: strict,
|
||||
Manual: manual,
|
||||
Debug: debug,
|
||||
},
|
||||
}
|
||||
|
|
|
@ -16,8 +16,11 @@ var noticeCmd = &cobra.Command{
|
|||
Args: cobra.NoArgs,
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
env := &runtime.Terminal{
|
||||
CmdFlags: &runtime.Flags{},
|
||||
CmdFlags: &runtime.Flags{
|
||||
SaveCache: true,
|
||||
},
|
||||
}
|
||||
|
||||
env.Init()
|
||||
defer env.Close()
|
||||
|
||||
|
|
151
src/cli/print.go
151
src/cli/print.go
|
@ -21,6 +21,7 @@ var (
|
|||
cleared bool
|
||||
cached bool
|
||||
jobCount int
|
||||
saveCache bool
|
||||
|
||||
command string
|
||||
shellVersion string
|
||||
|
@ -30,74 +31,81 @@ var (
|
|||
)
|
||||
|
||||
// printCmd represents the prompt command
|
||||
var printCmd = &cobra.Command{
|
||||
Use: "print [debug|primary|secondary|transient|right|tooltip|valid|error]",
|
||||
Short: "Print the prompt/context",
|
||||
Long: "Print one of the prompts based on the location/use-case.",
|
||||
ValidArgs: []string{
|
||||
"debug",
|
||||
"primary",
|
||||
"secondary",
|
||||
"transient",
|
||||
"right",
|
||||
"tooltip",
|
||||
"valid",
|
||||
"error",
|
||||
},
|
||||
Args: NoArgsOrOneValidArg,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
_ = cmd.Help()
|
||||
return
|
||||
}
|
||||
|
||||
flags := &runtime.Flags{
|
||||
Config: configFlag,
|
||||
PWD: pwd,
|
||||
PSWD: pswd,
|
||||
ErrorCode: status,
|
||||
PipeStatus: pipestatus,
|
||||
ExecutionTime: timing,
|
||||
StackCount: stackCount,
|
||||
TerminalWidth: terminalWidth,
|
||||
Eval: eval,
|
||||
Shell: shellName,
|
||||
ShellVersion: shellVersion,
|
||||
Plain: plain,
|
||||
Primary: args[0] == "primary",
|
||||
Cleared: cleared,
|
||||
NoExitCode: noStatus,
|
||||
Column: column,
|
||||
JobCount: jobCount,
|
||||
}
|
||||
|
||||
eng := prompt.New(flags)
|
||||
defer eng.Env.Close()
|
||||
|
||||
switch args[0] {
|
||||
case "debug":
|
||||
fmt.Print(eng.ExtraPrompt(prompt.Debug))
|
||||
case "primary":
|
||||
fmt.Print(eng.Primary())
|
||||
case "secondary":
|
||||
fmt.Print(eng.ExtraPrompt(prompt.Secondary))
|
||||
case "transient":
|
||||
fmt.Print(eng.ExtraPrompt(prompt.Transient))
|
||||
case "right":
|
||||
fmt.Print(eng.RPrompt())
|
||||
case "tooltip":
|
||||
fmt.Print(eng.Tooltip(command))
|
||||
case "valid":
|
||||
fmt.Print(eng.ExtraPrompt(prompt.Valid))
|
||||
case "error":
|
||||
fmt.Print(eng.ExtraPrompt(prompt.Error))
|
||||
default:
|
||||
_ = cmd.Help()
|
||||
}
|
||||
},
|
||||
}
|
||||
var printCmd = createPrintCmd()
|
||||
|
||||
func init() {
|
||||
RootCmd.AddCommand(printCmd)
|
||||
}
|
||||
|
||||
func createPrintCmd() *cobra.Command {
|
||||
printCmd := &cobra.Command{
|
||||
Use: "print [debug|primary|secondary|transient|right|tooltip|valid|error]",
|
||||
Short: "Print the prompt/context",
|
||||
Long: "Print one of the prompts based on the location/use-case.",
|
||||
ValidArgs: []string{
|
||||
"debug",
|
||||
"primary",
|
||||
"secondary",
|
||||
"transient",
|
||||
"right",
|
||||
"tooltip",
|
||||
"valid",
|
||||
"error",
|
||||
},
|
||||
Args: NoArgsOrOneValidArg,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) == 0 {
|
||||
_ = cmd.Help()
|
||||
return
|
||||
}
|
||||
|
||||
flags := &runtime.Flags{
|
||||
Config: configFlag,
|
||||
PWD: pwd,
|
||||
PSWD: pswd,
|
||||
ErrorCode: status,
|
||||
PipeStatus: pipestatus,
|
||||
ExecutionTime: timing,
|
||||
StackCount: stackCount,
|
||||
TerminalWidth: terminalWidth,
|
||||
Eval: eval,
|
||||
Shell: shellName,
|
||||
ShellVersion: shellVersion,
|
||||
Plain: plain,
|
||||
Primary: args[0] == "primary",
|
||||
Cleared: cleared,
|
||||
NoExitCode: noStatus,
|
||||
Column: column,
|
||||
JobCount: jobCount,
|
||||
SaveCache: saveCache,
|
||||
}
|
||||
|
||||
eng := prompt.New(flags)
|
||||
defer eng.Env.Close()
|
||||
|
||||
switch args[0] {
|
||||
case "debug":
|
||||
fmt.Print(eng.ExtraPrompt(prompt.Debug))
|
||||
case "primary":
|
||||
fmt.Print(eng.Primary())
|
||||
case "secondary":
|
||||
fmt.Print(eng.ExtraPrompt(prompt.Secondary))
|
||||
case "transient":
|
||||
fmt.Print(eng.ExtraPrompt(prompt.Transient))
|
||||
case "right":
|
||||
fmt.Print(eng.RPrompt())
|
||||
case "tooltip":
|
||||
fmt.Print(eng.Tooltip(command))
|
||||
case "valid":
|
||||
fmt.Print(eng.ExtraPrompt(prompt.Valid))
|
||||
case "error":
|
||||
fmt.Print(eng.ExtraPrompt(prompt.Error))
|
||||
default:
|
||||
_ = cmd.Help()
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
printCmd.Flags().StringVar(&pwd, "pwd", "", "current working directory")
|
||||
printCmd.Flags().StringVar(&pswd, "pswd", "", "current working directory (according to pwsh)")
|
||||
printCmd.Flags().StringVar(&shellName, "shell", "", "the shell to print for")
|
||||
|
@ -114,11 +122,18 @@ func init() {
|
|||
printCmd.Flags().BoolVar(&eval, "eval", false, "output the prompt for eval")
|
||||
printCmd.Flags().IntVar(&column, "column", 0, "the column position of the cursor")
|
||||
printCmd.Flags().IntVar(&jobCount, "job-count", 0, "number of background jobs")
|
||||
printCmd.Flags().BoolVar(&saveCache, "save-cache", false, "save updated cache to file")
|
||||
|
||||
// Deprecated flags, keep to not break CLI integration
|
||||
// Deprecated flags, should be kept to avoid breaking CLI integration.
|
||||
printCmd.Flags().IntVarP(&status, "error", "e", 0, "last exit code")
|
||||
printCmd.Flags().BoolVar(&noStatus, "no-exit-code", false, "no valid exit code (cancelled or no command yet)")
|
||||
printCmd.Flags().BoolVar(&cached, "cached", false, "use a cached prompt")
|
||||
|
||||
RootCmd.AddCommand(printCmd)
|
||||
// Hide flags that are deprecated or for internal use only.
|
||||
_ = printCmd.Flags().MarkHidden("error")
|
||||
_ = printCmd.Flags().MarkHidden("no-exit-code")
|
||||
_ = printCmd.Flags().MarkHidden("cached")
|
||||
_ = printCmd.Flags().MarkHidden("save-cache")
|
||||
|
||||
return printCmd
|
||||
}
|
||||
|
|
|
@ -6,10 +6,11 @@ import (
|
|||
|
||||
// promptCmd represents the prompt command
|
||||
var promptCmd = &cobra.Command{
|
||||
Use: "prompt",
|
||||
Short: "Set up the prompt for your shell (deprecated)",
|
||||
Long: `Set up the prompt for your shell. (deprecated)`,
|
||||
Args: cobra.NoArgs,
|
||||
Use: "prompt",
|
||||
Short: "Set up the prompt for your shell (deprecated)",
|
||||
Long: `Set up the prompt for your shell. (deprecated)`,
|
||||
Hidden: true,
|
||||
Args: cobra.NoArgs,
|
||||
Run: func(cmd *cobra.Command, _ []string) {
|
||||
_ = cmd.Help()
|
||||
},
|
||||
|
@ -17,8 +18,8 @@ var promptCmd = &cobra.Command{
|
|||
|
||||
func init() {
|
||||
// legacy support
|
||||
promptCmd.AddCommand(initCmd)
|
||||
promptCmd.AddCommand(debugCmd)
|
||||
promptCmd.AddCommand(printCmd)
|
||||
promptCmd.AddCommand(createInitCmd())
|
||||
promptCmd.AddCommand(createDebugCmd())
|
||||
promptCmd.AddCommand(createPrintCmd())
|
||||
RootCmd.AddCommand(promptCmd)
|
||||
}
|
||||
|
|
|
@ -49,7 +49,13 @@ var (
|
|||
|
||||
func init() {
|
||||
RootCmd.PersistentFlags().StringVarP(&configFlag, "config", "c", "", "config file path")
|
||||
RootCmd.Flags().BoolVarP(&initialize, "init", "i", false, "init (deprecated)")
|
||||
RootCmd.Flags().BoolVar(&displayVersion, "version", false, "version")
|
||||
RootCmd.Flags().StringVarP(&shellName, "shell", "s", "", "shell (deprecated)")
|
||||
|
||||
// Deprecated flags, should be kept to avoid breaking CLI integration.
|
||||
RootCmd.Flags().BoolVarP(&initialize, "init", "i", false, "init")
|
||||
RootCmd.Flags().StringVarP(&shellName, "shell", "s", "", "shell")
|
||||
|
||||
// Hide flags that are deprecated or for internal use only.
|
||||
_ = RootCmd.Flags().MarkHidden("init")
|
||||
_ = RootCmd.Flags().MarkHidden("shell")
|
||||
}
|
||||
|
|
|
@ -19,7 +19,13 @@ var toggleCmd = &cobra.Command{
|
|||
_ = cmd.Help()
|
||||
return
|
||||
}
|
||||
env := &runtime.Terminal{}
|
||||
|
||||
env := &runtime.Terminal{
|
||||
CmdFlags: &runtime.Flags{
|
||||
SaveCache: true,
|
||||
},
|
||||
}
|
||||
|
||||
env.Init()
|
||||
defer env.Close()
|
||||
|
||||
|
|
|
@ -108,17 +108,19 @@ func (e *Engine) pwd() {
|
|||
}
|
||||
|
||||
func (e *Engine) getNewline() string {
|
||||
// WARP terminal will remove \n from the prompt, so we hack a newline in.
|
||||
// For Elvish, we do this to prevent cutting off a right-aligned block.
|
||||
if e.isWarp() || e.Env.Shell() == shell.ELVISH {
|
||||
if e.Plain || e.Env.Flags().Debug {
|
||||
return "\n"
|
||||
}
|
||||
|
||||
// Warp terminal will remove a newline character ('\n') from the prompt, so we hack it in.
|
||||
// For Elvish on Windows, we do this to prevent cutting off a right-aligned block.
|
||||
if e.isWarp() || (e.Env.Shell() == shell.ELVISH && e.Env.GOOS() == runtime.WINDOWS) {
|
||||
return terminal.LineBreak()
|
||||
}
|
||||
|
||||
// TCSH needs a space before the LITERAL newline character or it will not render correctly
|
||||
// don't ask why, it be like that sometimes.
|
||||
// https://unix.stackexchange.com/questions/99101/properly-defining-a-multi-line-prompt-in-tcsh#comment1342462_322189
|
||||
// To avoid improper translations in Tcsh, we use an invisible word joiner character (U+2060) to separate a newline from possible preceding escape sequences.
|
||||
if e.Env.Shell() == shell.TCSH {
|
||||
return ` \n`
|
||||
return "\u2060\\n"
|
||||
}
|
||||
|
||||
return "\n"
|
||||
|
@ -506,6 +508,17 @@ func (e *Engine) adjustTrailingDiamondColorOverrides() {
|
|||
}
|
||||
}
|
||||
|
||||
func (e *Engine) rectifyTerminalWidth(diff int) {
|
||||
// Since the terminal width may not be given by the CLI flag, we should always call this here.
|
||||
_, err := e.Env.TerminalWidth()
|
||||
if err != nil {
|
||||
// Skip when we're unable to determine the terminal width.
|
||||
return
|
||||
}
|
||||
|
||||
e.Env.Flags().TerminalWidth += diff
|
||||
}
|
||||
|
||||
// New returns a prompt engine initialized with the
|
||||
// given configuration options, and is ready to print any
|
||||
// of the prompt components.
|
||||
|
@ -532,9 +545,16 @@ func New(flags *runtime.Flags) *Engine {
|
|||
}
|
||||
|
||||
switch env.Shell() {
|
||||
case shell.ELVISH:
|
||||
// In Elvish, a prompt line will always wrap when the cursor reaches the rightmost cell on the terminal screen.
|
||||
// We have to reduce the terminal width by 1 so a right-aligned block will not be broken.
|
||||
case shell.XONSH:
|
||||
// In Xonsh, the behavior of wrapping at the end of a prompt line is inconsistent across platforms.
|
||||
// On Windows, it wraps before the rightmost cell on the terminal screen, that is, the rightmost cell is never available for a prompt line.
|
||||
if eng.Env.GOOS() == runtime.WINDOWS {
|
||||
eng.rectifyTerminalWidth(-1)
|
||||
}
|
||||
case shell.TCSH, shell.ELVISH:
|
||||
// In Tcsh, newlines in a prompt are badly translated.
|
||||
// No silver bullet here. We have to reduce the terminal width by 1 so a right-aligned block will not be broken.
|
||||
// In Elvish, the behavior is similar to that in Xonsh, but we do this for all platforms.
|
||||
eng.rectifyTerminalWidth(-1)
|
||||
case shell.PWSH, shell.PWSH5:
|
||||
// when in PowerShell, and force patching the bleed bug
|
||||
|
@ -548,14 +568,3 @@ func New(flags *runtime.Flags) *Engine {
|
|||
|
||||
return eng
|
||||
}
|
||||
|
||||
func (e *Engine) rectifyTerminalWidth(diff int) {
|
||||
// Since the terminal width may not be given by the CLI flag, we should always call this here.
|
||||
_, err := e.Env.TerminalWidth()
|
||||
if err != nil {
|
||||
// Skip when we're unable to determine the terminal width.
|
||||
return
|
||||
}
|
||||
|
||||
e.Env.Flags().TerminalWidth += diff
|
||||
}
|
||||
|
|
|
@ -101,23 +101,22 @@ func (e *Engine) ExtraPrompt(promptType ExtraPromptType) string {
|
|||
switch e.Env.Shell() {
|
||||
case shell.ZSH:
|
||||
if promptType == Transient {
|
||||
if !e.Env.Flags().Eval {
|
||||
break
|
||||
}
|
||||
|
||||
prompt := fmt.Sprintf("PS1=%s", shell.QuotePosixStr(str))
|
||||
// empty RPROMPT
|
||||
prompt += "\nRPROMPT=''"
|
||||
return prompt
|
||||
}
|
||||
return str
|
||||
case shell.PWSH, shell.PWSH5:
|
||||
if promptType == Transient {
|
||||
// clear the line afterwards to prevent text from being written on the same line
|
||||
// see https://github.com/JanDeDobbeleer/oh-my-posh/issues/3628
|
||||
return str + terminal.ClearAfter()
|
||||
}
|
||||
|
||||
return str
|
||||
case shell.CMD, shell.BASH, shell.FISH, shell.NU, shell.GENERIC:
|
||||
return str
|
||||
}
|
||||
|
||||
return ""
|
||||
return str
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package prompt
|
|||
|
||||
import (
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/config"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/runtime"
|
||||
"github.com/jandedobbeleer/oh-my-posh/src/shell"
|
||||
)
|
||||
|
||||
func (e *Engine) RPrompt() string {
|
||||
|
@ -29,5 +31,10 @@ func (e *Engine) RPrompt() string {
|
|||
text, length := e.renderBlockSegments(rprompt)
|
||||
e.rpromptLength = length
|
||||
|
||||
if e.Env.Shell() == shell.ELVISH && e.Env.GOOS() != runtime.WINDOWS {
|
||||
// Workaround to align with a right-aligned block on non-Windows systems.
|
||||
text += " "
|
||||
}
|
||||
|
||||
return text
|
||||
}
|
||||
|
|
|
@ -68,7 +68,6 @@ type Environment interface {
|
|||
Connection(connectionType ConnectionType) (*Connection, error)
|
||||
TemplateCache() *cache.Template
|
||||
LoadTemplateCache()
|
||||
SetPromptCount()
|
||||
CursorPosition() (row, col int)
|
||||
SystemInfo() (*SystemInfo, error)
|
||||
Debug(message string)
|
||||
|
@ -92,7 +91,6 @@ type Flags struct {
|
|||
TerminalWidth int
|
||||
Strict bool
|
||||
Debug bool
|
||||
Manual bool
|
||||
Plain bool
|
||||
Primary bool
|
||||
HasTransient bool
|
||||
|
@ -101,6 +99,7 @@ type Flags struct {
|
|||
NoExitCode bool
|
||||
Column int
|
||||
JobCount int
|
||||
SaveCache bool
|
||||
}
|
||||
|
||||
type CommandError struct {
|
||||
|
|
|
@ -281,10 +281,6 @@ func (env *Environment) DirIsWritable(path string) bool {
|
|||
return args.Bool(0)
|
||||
}
|
||||
|
||||
func (env *Environment) SetPromptCount() {
|
||||
_ = env.Called()
|
||||
}
|
||||
|
||||
func (env *Environment) CursorPosition() (int, int) {
|
||||
args := env.Called()
|
||||
return args.Int(0), args.Int(1)
|
||||
|
|
|
@ -67,12 +67,13 @@ func (term *Terminal) Init() {
|
|||
|
||||
initCache := func(fileName string) *cache.File {
|
||||
cache := &cache.File{}
|
||||
cache.Init(filepath.Join(term.CachePath(), fileName))
|
||||
cache.Init(filepath.Join(term.CachePath(), fileName), term.CmdFlags.SaveCache)
|
||||
return cache
|
||||
}
|
||||
|
||||
term.deviceCache = initCache(cache.FileName)
|
||||
term.sessionCache = initCache(cache.SessionFileName)
|
||||
term.setPromptCount()
|
||||
|
||||
term.ResolveConfigPath()
|
||||
|
||||
|
@ -81,8 +82,6 @@ func (term *Terminal) Init() {
|
|||
}
|
||||
|
||||
term.tmplCache = &cache.Template{}
|
||||
|
||||
term.SetPromptCount()
|
||||
}
|
||||
|
||||
func (term *Terminal) ResolveConfigPath() {
|
||||
|
@ -737,27 +736,20 @@ func dirMatchesOneOf(dir, home, goos string, regexes []string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (term *Terminal) SetPromptCount() {
|
||||
func (term *Terminal) setPromptCount() {
|
||||
defer term.Trace(time.Now())
|
||||
|
||||
countStr := os.Getenv("POSH_PROMPT_COUNT")
|
||||
if len(countStr) > 0 {
|
||||
// this counter is incremented by the shell
|
||||
count, err := strconv.Atoi(countStr)
|
||||
if err == nil {
|
||||
term.CmdFlags.PromptCount = count
|
||||
return
|
||||
}
|
||||
}
|
||||
var count int
|
||||
if val, found := term.Session().Get(cache.PROMPTCOUNTCACHE); found {
|
||||
count, _ = strconv.Atoi(val)
|
||||
}
|
||||
// only write to cache if we're the primary prompt
|
||||
|
||||
// Only update the count if we're generating a primary prompt.
|
||||
if term.CmdFlags.Primary {
|
||||
count++
|
||||
term.Session().Set(cache.PROMPTCOUNTCACHE, strconv.Itoa(count), 1440)
|
||||
}
|
||||
|
||||
term.CmdFlags.PromptCount = count
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package shell
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
@ -13,13 +12,13 @@ var bashInit string
|
|||
func (f Feature) Bash() Code {
|
||||
switch f {
|
||||
case CursorPositioning:
|
||||
return "_omp_cursor_positioning=1"
|
||||
return unixCursorPositioning
|
||||
case FTCSMarks:
|
||||
return "_omp_ftcs_marks=1"
|
||||
return unixFTCSMarks
|
||||
case Upgrade:
|
||||
return `"$_omp_executable" upgrade`
|
||||
return unixUpgrade
|
||||
case Notice:
|
||||
return `"$_omp_executable" notice`
|
||||
return unixNotice
|
||||
case PromptMark, RPrompt, PoshGit, Azure, LineError, Jobs, Tooltips, Transient:
|
||||
fallthrough
|
||||
default:
|
||||
|
@ -32,42 +31,5 @@ func QuotePosixStr(str string) string {
|
|||
return "''"
|
||||
}
|
||||
|
||||
needQuoting := false
|
||||
var b strings.Builder
|
||||
for _, r := range str {
|
||||
normal := false
|
||||
switch r {
|
||||
case '!', ';', '"', '(', ')', '[', ']', '{', '}', '$', '|', '&', '>', '<', '`', ' ', '#', '~', '*', '?', '=':
|
||||
b.WriteRune(r)
|
||||
case '\\', '\'':
|
||||
b.WriteByte('\\')
|
||||
b.WriteRune(r)
|
||||
case '\a':
|
||||
b.WriteString(`\a`)
|
||||
case '\b':
|
||||
b.WriteString(`\b`)
|
||||
case '\f':
|
||||
b.WriteString(`\f`)
|
||||
case '\n':
|
||||
b.WriteString(`\n`)
|
||||
case '\r':
|
||||
b.WriteString(`\r`)
|
||||
case '\t':
|
||||
b.WriteString(`\t`)
|
||||
case '\v':
|
||||
b.WriteString(`\v`)
|
||||
default:
|
||||
b.WriteRune(r)
|
||||
normal = true
|
||||
}
|
||||
if !normal {
|
||||
needQuoting = true
|
||||
}
|
||||
}
|
||||
// the quoting form $'...' is used for a string contains any special characters
|
||||
if needQuoting {
|
||||
return fmt.Sprintf("$'%s'", b.String())
|
||||
}
|
||||
|
||||
return b.String()
|
||||
return fmt.Sprintf("$'%s'", strings.NewReplacer(`\`, `\\`, "'", `\'`).Replace(str))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -17,3 +18,17 @@ _omp_cursor_positioning=1`
|
|||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestQuotePosixStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: "", expected: "''"},
|
||||
{str: `/tmp/"omp's dir"/oh-my-posh`, expected: `$'/tmp/"omp\'s dir"/oh-my-posh'`},
|
||||
{str: `C:/tmp\omp's dir/oh-my-posh.exe`, expected: `$'C:/tmp\\omp\'s dir/oh-my-posh.exe'`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, QuotePosixStr(tc.str), fmt.Sprintf("QuotePosixStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ package shell
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -16,23 +14,32 @@ func (f Feature) Cmd() Code {
|
|||
return "transient_enabled = true"
|
||||
case RPrompt:
|
||||
return "rprompt_enabled = true"
|
||||
case FTCSMarks:
|
||||
return "ftcs_marks_enabled = true"
|
||||
case Tooltips:
|
||||
return "enable_tooltips()"
|
||||
case Upgrade:
|
||||
return "os.execute(string.format('%s upgrade', omp_exe()))"
|
||||
return `os.execute(string.format('"%s" upgrade', omp_executable))`
|
||||
case Notice:
|
||||
return "os.execute(string.format('%s notice', omp_exe()))"
|
||||
case PromptMark, PoshGit, Azure, LineError, Jobs, FTCSMarks, CursorPositioning:
|
||||
return `os.execute(string.format('"%s" notice', omp_executable))`
|
||||
case PromptMark, PoshGit, Azure, LineError, Jobs, CursorPositioning:
|
||||
fallthrough
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func quoteLuaStr(str string) string {
|
||||
func escapeLuaStr(str string) string {
|
||||
if len(str) == 0 {
|
||||
return "''"
|
||||
return str
|
||||
}
|
||||
|
||||
return fmt.Sprintf("'%s'", strings.NewReplacer(`\`, `\\`, `'`, `\'`).Replace(str))
|
||||
// We only replace a minimal set of special characters with corresponding escape sequences, without adding surrounding quotes.
|
||||
// That way the result can be later quoted with either single or double quotes in a Lua script.
|
||||
return strings.NewReplacer(
|
||||
`\`, `\\`,
|
||||
"'", `\'`,
|
||||
`"`, `\"`,
|
||||
"\n", `\n`,
|
||||
"\r", `\r`,
|
||||
).Replace(str)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -12,9 +13,24 @@ func TestCmdFeatures(t *testing.T) {
|
|||
want := `// these are the features
|
||||
enable_tooltips()
|
||||
transient_enabled = true
|
||||
os.execute(string.format('%s upgrade', omp_exe()))
|
||||
os.execute(string.format('%s notice', omp_exe()))
|
||||
ftcs_marks_enabled = true
|
||||
os.execute(string.format('"%s" upgrade', omp_executable))
|
||||
os.execute(string.format('"%s" notice', omp_executable))
|
||||
rprompt_enabled = true`
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestEscapeLuaStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: "", expected: ""},
|
||||
{str: `/tmp/"omp's dir"/oh-my-posh`, expected: `/tmp/\"omp\'s dir\"/oh-my-posh`},
|
||||
{str: `C:/tmp\omp's dir/oh-my-posh.exe`, expected: `C:/tmp\\omp\'s dir/oh-my-posh.exe`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, escapeLuaStr(tc.str), fmt.Sprintf("escapeLuaStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,13 @@ import "strings"
|
|||
|
||||
type Code string
|
||||
|
||||
const (
|
||||
unixFTCSMarks Code = "_omp_ftcs_marks=1"
|
||||
unixCursorPositioning Code = "_omp_cursor_positioning=1"
|
||||
unixUpgrade Code = `"$_omp_executable" upgrade`
|
||||
unixNotice Code = `"$_omp_executable" notice`
|
||||
)
|
||||
|
||||
func (c Code) Indent(spaces int) Code {
|
||||
return Code(strings.Repeat(" ", spaces) + string(c))
|
||||
}
|
||||
|
|
|
@ -10,9 +10,9 @@ var elvishInit string
|
|||
func (f Feature) Elvish() Code {
|
||||
switch f {
|
||||
case Upgrade:
|
||||
return unixUpgrade
|
||||
return "$_omp_executable upgrade"
|
||||
case Notice:
|
||||
return unixNotice
|
||||
return "$_omp_executable notice"
|
||||
case PromptMark, RPrompt, PoshGit, Azure, LineError, Jobs, CursorPositioning, Tooltips, Transient, FTCSMarks:
|
||||
fallthrough
|
||||
default:
|
||||
|
|
|
@ -2,7 +2,6 @@ package shell
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
@ -35,27 +34,6 @@ func quoteFishStr(str string) string {
|
|||
if len(str) == 0 {
|
||||
return "''"
|
||||
}
|
||||
needQuoting := false
|
||||
var b strings.Builder
|
||||
for _, r := range str {
|
||||
normal := false
|
||||
switch r {
|
||||
case ';', '"', '(', ')', '[', ']', '{', '}', '$', '|', '&', '>', '<', ' ', '#', '~', '*', '?', '=':
|
||||
b.WriteRune(r)
|
||||
case '\\', '\'':
|
||||
b.WriteByte('\\')
|
||||
b.WriteRune(r)
|
||||
default:
|
||||
b.WriteRune(r)
|
||||
normal = true
|
||||
}
|
||||
if !normal {
|
||||
needQuoting = true
|
||||
}
|
||||
}
|
||||
// single quotes are used when the string contains any special characters
|
||||
if needQuoting {
|
||||
return fmt.Sprintf("'%s'", b.String())
|
||||
}
|
||||
return b.String()
|
||||
|
||||
return fmt.Sprintf("'%s'", strings.NewReplacer(`\`, `\\`, "'", `\'`).Replace(str))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -13,9 +14,23 @@ func TestFishFeatures(t *testing.T) {
|
|||
enable_poshtooltips
|
||||
set --global _omp_transient_prompt 1
|
||||
set --global _omp_ftcs_marks 1
|
||||
$_omp_executable upgrade
|
||||
$_omp_executable notice
|
||||
"$_omp_executable" upgrade
|
||||
"$_omp_executable" notice
|
||||
set --global _omp_prompt_mark 1`
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestQuoteFishStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: "", expected: "''"},
|
||||
{str: `/tmp/"omp's dir"/oh-my-posh`, expected: `'/tmp/"omp\'s dir"/oh-my-posh'`},
|
||||
{str: `C:/tmp\omp's dir/oh-my-posh.exe`, expected: `'C:/tmp\\omp\'s dir/oh-my-posh.exe'`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, quoteFishStr(tc.str), fmt.Sprintf("quoteFishStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,6 +73,9 @@ func GetFormats(shell string) *Formats {
|
|||
ITermPromptMark: "%{$(iterm2_prompt_mark)%}",
|
||||
ITermCurrentDir: "%%{\x1b]1337;CurrentDir=%s\x07%%}",
|
||||
ITermRemoteHost: "%%{\x1b]1337;RemoteHost=%s@%s\x07%%}",
|
||||
EscapeSequences: map[rune]string{
|
||||
'%': "%%",
|
||||
},
|
||||
}
|
||||
default:
|
||||
formats = &Formats{
|
||||
|
@ -98,10 +101,9 @@ func GetFormats(shell string) *Formats {
|
|||
}
|
||||
}
|
||||
|
||||
if shell == ZSH {
|
||||
formats.EscapeSequences = map[rune]string{
|
||||
'%': "%%",
|
||||
}
|
||||
if shell == TCSH {
|
||||
formats.EscapeSequences['\\'] = `\\`
|
||||
formats.EscapeSequences['!'] = `\!`
|
||||
}
|
||||
|
||||
return formats
|
||||
|
|
|
@ -49,10 +49,6 @@ func Init(env runtime.Environment, feats Features) string {
|
|||
additionalParams += " --strict"
|
||||
}
|
||||
|
||||
if env.Flags().Manual {
|
||||
additionalParams += " --manual"
|
||||
}
|
||||
|
||||
var command, config string
|
||||
|
||||
switch shell {
|
||||
|
@ -72,7 +68,7 @@ func Init(env runtime.Environment, feats Features) string {
|
|||
createNuInit(env, feats)
|
||||
return ""
|
||||
default:
|
||||
return fmt.Sprintf("echo \"No initialization script available for %s\"", shell)
|
||||
return fmt.Sprintf(`echo "%s is not supported by Oh My Posh"`, shell)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,22 +101,24 @@ func PrintInit(env runtime.Environment, features Features, startTime *time.Time)
|
|||
configFile = quoteFishStr(configFile)
|
||||
script = fishInit
|
||||
case CMD:
|
||||
executable = quoteLuaStr(executable)
|
||||
configFile = quoteLuaStr(configFile)
|
||||
executable = escapeLuaStr(executable)
|
||||
configFile = escapeLuaStr(configFile)
|
||||
script = cmdInit
|
||||
case NU:
|
||||
executable = quoteNuStr(executable)
|
||||
configFile = quoteNuStr(configFile)
|
||||
script = nuInit
|
||||
case TCSH:
|
||||
executable = QuotePosixStr(executable)
|
||||
configFile = QuotePosixStr(configFile)
|
||||
executable = quoteCshStr(executable)
|
||||
configFile = quoteCshStr(configFile)
|
||||
script = tcshInit
|
||||
case ELVISH:
|
||||
executable = quotePwshOrElvishStr(executable)
|
||||
configFile = quotePwshOrElvishStr(configFile)
|
||||
script = elvishInit
|
||||
case XONSH:
|
||||
executable = quotePythonStr(executable)
|
||||
configFile = quotePythonStr(configFile)
|
||||
script = xonshInit
|
||||
default:
|
||||
return fmt.Sprintf("echo \"No initialization script available for %s\"", shell)
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestQuotePwshOrElvishStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: ``, expected: `''`},
|
||||
{str: `/tmp/oh-my-posh`, expected: `'/tmp/oh-my-posh'`},
|
||||
{str: `/tmp/omp's dir/oh-my-posh`, expected: `'/tmp/omp''s dir/oh-my-posh'`},
|
||||
{str: `C:\tmp\oh-my-posh.exe`, expected: `'C:\tmp\oh-my-posh.exe'`},
|
||||
{str: `C:\tmp\omp's dir\oh-my-posh.exe`, expected: `'C:\tmp\omp''s dir\oh-my-posh.exe'`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, quotePwshOrElvishStr(tc.str), fmt.Sprintf("quotePwshStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuotePosixStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: ``, expected: `''`},
|
||||
{str: `/tmp/oh-my-posh`, expected: `/tmp/oh-my-posh`},
|
||||
{str: `/tmp/omp's dir/oh-my-posh`, expected: `$'/tmp/omp\'s dir/oh-my-posh'`},
|
||||
{str: `C:/tmp/oh-my-posh.exe`, expected: `C:/tmp/oh-my-posh.exe`},
|
||||
{str: `C:/tmp/omp's dir/oh-my-posh.exe`, expected: `$'C:/tmp/omp\'s dir/oh-my-posh.exe'`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, QuotePosixStr(tc.str), fmt.Sprintf("quotePosixStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuoteFishStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: ``, expected: `''`},
|
||||
{str: `/tmp/oh-my-posh`, expected: `/tmp/oh-my-posh`},
|
||||
{str: `/tmp/omp's dir/oh-my-posh`, expected: `'/tmp/omp\'s dir/oh-my-posh'`},
|
||||
{str: `C:/tmp/oh-my-posh.exe`, expected: `C:/tmp/oh-my-posh.exe`},
|
||||
{str: `C:/tmp/omp's dir/oh-my-posh.exe`, expected: `'C:/tmp/omp\'s dir/oh-my-posh.exe'`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, quoteFishStr(tc.str), fmt.Sprintf("quoteFishStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuoteLuaStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: ``, expected: `''`},
|
||||
{str: `/tmp/oh-my-posh`, expected: `'/tmp/oh-my-posh'`},
|
||||
{str: `/tmp/omp's dir/oh-my-posh`, expected: `'/tmp/omp\'s dir/oh-my-posh'`},
|
||||
{str: `C:/tmp/oh-my-posh.exe`, expected: `'C:/tmp/oh-my-posh.exe'`},
|
||||
{str: `C:/tmp/omp's dir/oh-my-posh.exe`, expected: `'C:/tmp/omp\'s dir/oh-my-posh.exe'`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, quoteLuaStr(tc.str), fmt.Sprintf("quoteLuaStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
||||
func TestQuoteNuStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: ``, expected: `''`},
|
||||
{str: `/tmp/oh-my-posh`, expected: `"/tmp/oh-my-posh"`},
|
||||
{str: `/tmp/omp's dir/oh-my-posh`, expected: `"/tmp/omp's dir/oh-my-posh"`},
|
||||
{str: `C:/tmp/oh-my-posh.exe`, expected: `"C:/tmp/oh-my-posh.exe"`},
|
||||
{str: `C:/tmp/omp's dir/oh-my-posh.exe`, expected: `"C:/tmp/omp's dir/oh-my-posh.exe"`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, quoteNuStr(tc.str), fmt.Sprintf("quoteNuStr: %s", tc.str))
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@ package shell
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -17,7 +16,7 @@ var nuInit string
|
|||
func (f Feature) Nu() Code {
|
||||
switch f {
|
||||
case Transient:
|
||||
return `$env.TRANSIENT_PROMPT_COMMAND = { ^$_omp_executable print transient $"--config=($env.POSH_THEME)" --shell=nu $"--shell-version=($env.POSH_SHELL_VERSION)" $"--execution-time=(posh_cmd_duration)" $"--status=($env.LAST_EXIT_CODE)" $"--terminal-width=(posh_width)" }` //nolint: lll
|
||||
return `$env.TRANSIENT_PROMPT_COMMAND = {|| _omp_get_prompt transient }`
|
||||
case Upgrade:
|
||||
return "^$_omp_executable upgrade"
|
||||
case Notice:
|
||||
|
@ -33,12 +32,13 @@ func quoteNuStr(str string) string {
|
|||
if len(str) == 0 {
|
||||
return "''"
|
||||
}
|
||||
|
||||
return fmt.Sprintf(`"%s"`, strings.NewReplacer(`\`, `\\`, `"`, `\"`).Replace(str))
|
||||
}
|
||||
|
||||
func createNuInit(env runtime.Environment, features Features) {
|
||||
initPath := filepath.Join(env.Home(), ".oh-my-posh.nu")
|
||||
f, err := os.OpenFile(initPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0755)
|
||||
f, err := os.OpenFile(initPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0o755)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -9,11 +10,24 @@ import (
|
|||
func TestNuFeatures(t *testing.T) {
|
||||
got := allFeatures.Lines(NU).String("// these are the features")
|
||||
|
||||
//nolint: lll
|
||||
want := `// these are the features
|
||||
$env.TRANSIENT_PROMPT_COMMAND = { ^$_omp_executable print transient $"--config=($env.POSH_THEME)" --shell=nu $"--shell-version=($env.POSH_SHELL_VERSION)" $"--execution-time=(posh_cmd_duration)" $"--status=($env.LAST_EXIT_CODE)" $"--terminal-width=(posh_width)" }
|
||||
$env.TRANSIENT_PROMPT_COMMAND = {|| _omp_get_prompt transient }
|
||||
^$_omp_executable upgrade
|
||||
^$_omp_executable notice`
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestQuoteNuStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: "", expected: "''"},
|
||||
{str: `/tmp/"omp's dir"/oh-my-posh`, expected: `"/tmp/\"omp's dir\"/oh-my-posh"`},
|
||||
{str: `C:/tmp\omp's dir/oh-my-posh.exe`, expected: `"C:/tmp\\omp's dir/oh-my-posh.exe"`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, quoteNuStr(tc.str), fmt.Sprintf("quoteNuStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package shell
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
@ -38,5 +37,9 @@ func (f Feature) Pwsh() Code {
|
|||
}
|
||||
|
||||
func quotePwshOrElvishStr(str string) string {
|
||||
if len(str) == 0 {
|
||||
return "''"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("'%s'", strings.ReplaceAll(str, "'", "''"))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -24,3 +25,17 @@ $global:_ompFTCSMarks = $true
|
|||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestQuotePwshOrElvishStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: "", expected: "''"},
|
||||
{str: `/tmp/"omp's dir"/oh-my-posh`, expected: `'/tmp/"omp''s dir"/oh-my-posh'`},
|
||||
{str: `C:/tmp\omp's dir/oh-my-posh.exe`, expected: `'C:/tmp\omp''s dir/oh-my-posh.exe'`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, quotePwshOrElvishStr(tc.str), fmt.Sprintf("quotePwshOrElvishStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
export POSH_THEME=::CONFIG::
|
||||
export POSH_SHELL_VERSION=$BASH_VERSION
|
||||
export POWERLINE_COMMAND="oh-my-posh"
|
||||
export POWERLINE_COMMAND='oh-my-posh'
|
||||
export POSH_PID=$$
|
||||
export CONDA_PROMPT_MODIFIER=false
|
||||
export OSTYPE=$OSTYPE
|
||||
|
@ -10,12 +10,12 @@ if [[ $OSTYPE =~ ^(msys|cygwin) ]]; then
|
|||
fi
|
||||
|
||||
# global variables
|
||||
_omp_start_time=""
|
||||
_omp_start_time=''
|
||||
_omp_stack_count=0
|
||||
_omp_elapsed=-1
|
||||
_omp_no_exit_code="true"
|
||||
_omp_status_cache=0
|
||||
_omp_pipestatus_cache=0
|
||||
_omp_execution_time=-1
|
||||
_omp_no_status=true
|
||||
_omp_status=0
|
||||
_omp_pipestatus=0
|
||||
_omp_executable=::OMP::
|
||||
|
||||
# switches to enable/disable features
|
||||
|
@ -26,7 +26,11 @@ _omp_ftcs_marks=0
|
|||
PS0='${_omp_start_time:0:$((_omp_start_time="$(_omp_start_timer)",0))}$(_omp_ftcs_command_start)'
|
||||
|
||||
# set secondary prompt
|
||||
_omp_secondary_prompt=$("$_omp_executable" print secondary --shell=bash --shell-version="$BASH_VERSION")
|
||||
_omp_secondary_prompt=$(
|
||||
"$_omp_executable" print secondary \
|
||||
--shell=bash \
|
||||
--shell-version="$BASH_VERSION"
|
||||
)
|
||||
|
||||
function _omp_set_cursor_position() {
|
||||
# not supported in Midnight Commander
|
||||
|
@ -54,7 +58,7 @@ function _omp_start_timer() {
|
|||
|
||||
function _omp_ftcs_command_start() {
|
||||
if [[ $_omp_ftcs_marks == 1 ]]; then
|
||||
printf "\e]133;C\a"
|
||||
printf '\e]133;C\a'
|
||||
fi
|
||||
}
|
||||
|
||||
|
@ -63,26 +67,37 @@ function set_poshcontext() {
|
|||
return
|
||||
}
|
||||
|
||||
function _omp_print_primary() {
|
||||
# Avoid unexpected expansions.
|
||||
function _omp_get_primary() {
|
||||
# Avoid unexpected expansions when we're generating the prompt below.
|
||||
shopt -u promptvars
|
||||
trap 'shopt -s promptvars' RETURN
|
||||
|
||||
local prompt
|
||||
if shopt -oq posix; then
|
||||
# Disable in POSIX mode.
|
||||
prompt='[NOTICE: Oh My Posh prompt is not supported in POSIX mode]\n\u@\h:\w\$ '
|
||||
else
|
||||
prompt=$("$_omp_executable" print primary --shell=bash --shell-version="$BASH_VERSION" --status="$_omp_status_cache" --pipestatus="${_omp_pipestatus_cache[*]}" --execution-time="$_omp_elapsed" --stack-count="$_omp_stack_count" --no-status="$_omp_no_exit_code" --terminal-width="${COLUMNS-0}" | tr -d '\0')
|
||||
prompt=$(
|
||||
"$_omp_executable" print primary \
|
||||
--save-cache \
|
||||
--shell=bash \
|
||||
--shell-version="$BASH_VERSION" \
|
||||
--status="$_omp_status" \
|
||||
--pipestatus="${_omp_pipestatus[*]}" \
|
||||
--no-status="$_omp_no_status" \
|
||||
--execution-time="$_omp_execution_time" \
|
||||
--stack-count="$_omp_stack_count" \
|
||||
--terminal-width="${COLUMNS-0}" |
|
||||
tr -d '\0'
|
||||
)
|
||||
fi
|
||||
echo "${prompt@P}"
|
||||
|
||||
# Allow command substitution in PS0.
|
||||
shopt -s promptvars
|
||||
}
|
||||
|
||||
function _omp_print_secondary() {
|
||||
# Avoid unexpected expansions.
|
||||
function _omp_get_secondary() {
|
||||
# Avoid unexpected expansions when we're generating the prompt below.
|
||||
shopt -u promptvars
|
||||
trap 'shopt -s promptvars' RETURN
|
||||
|
||||
if shopt -oq posix; then
|
||||
# Disable in POSIX mode.
|
||||
|
@ -90,38 +105,39 @@ function _omp_print_secondary() {
|
|||
else
|
||||
echo "${_omp_secondary_prompt@P}"
|
||||
fi
|
||||
|
||||
# Allow command substitution in PS0.
|
||||
shopt -s promptvars
|
||||
}
|
||||
|
||||
function _omp_hook() {
|
||||
_omp_status_cache=$? _omp_pipestatus_cache=("${PIPESTATUS[@]}")
|
||||
_omp_status=$? _omp_pipestatus=("${PIPESTATUS[@]}")
|
||||
|
||||
if [[ ${#BP_PIPESTATUS[@]} -ge ${#_omp_pipestatus_cache[@]} ]]; then
|
||||
_omp_pipestatus_cache=("${BP_PIPESTATUS[@]}")
|
||||
if [[ ${#BP_PIPESTATUS[@]} -ge ${#_omp_pipestatus[@]} ]]; then
|
||||
_omp_pipestatus=("${BP_PIPESTATUS[@]}")
|
||||
fi
|
||||
|
||||
_omp_stack_count=$((${#DIRSTACK[@]} - 1))
|
||||
|
||||
_omp_execution_time=-1
|
||||
if [[ $_omp_start_time ]]; then
|
||||
local omp_now=$("$_omp_executable" get millis --shell=bash)
|
||||
_omp_elapsed=$((omp_now - _omp_start_time))
|
||||
_omp_start_time=""
|
||||
_omp_no_exit_code="false"
|
||||
local omp_now=$("$_omp_executable" get millis)
|
||||
_omp_execution_time=$((omp_now - _omp_start_time))
|
||||
_omp_no_status=false
|
||||
fi
|
||||
_omp_start_time=''
|
||||
|
||||
if [[ ${_omp_pipestatus_cache[-1]} != "$_omp_status_cache" ]]; then
|
||||
_omp_pipestatus_cache=("$_omp_status_cache")
|
||||
if [[ ${_omp_pipestatus[-1]} != "$_omp_status" ]]; then
|
||||
_omp_pipestatus=("$_omp_status")
|
||||
fi
|
||||
|
||||
set_poshcontext
|
||||
_omp_set_cursor_position
|
||||
|
||||
PS1='$(_omp_print_primary)'
|
||||
PS2='$(_omp_print_secondary)'
|
||||
PS1='$(_omp_get_primary)'
|
||||
PS2='$(_omp_get_secondary)'
|
||||
|
||||
return $_omp_status_cache
|
||||
# Ensure that command substitution works in a prompt string.
|
||||
shopt -s promptvars
|
||||
|
||||
return $_omp_status
|
||||
}
|
||||
|
||||
function _omp_install_hook() {
|
||||
|
@ -129,7 +145,7 @@ function _omp_install_hook() {
|
|||
|
||||
local cmd
|
||||
for cmd in "${PROMPT_COMMAND[@]}"; do
|
||||
if [[ $cmd = "_omp_hook" ]]; then
|
||||
if [[ $cmd = _omp_hook ]]; then
|
||||
return
|
||||
fi
|
||||
done
|
||||
|
|
|
@ -1,33 +1,55 @@
|
|||
set-env POSH_PID (to-string (randint 10000000000000 10000000000000000))
|
||||
set-env POSH_THEME ::CONFIG::
|
||||
set-env POSH_SHELL_VERSION (elvish --version)
|
||||
set-env POWERLINE_COMMAND 'oh-my-posh'
|
||||
set-env POSH_SHELL_VERSION $version
|
||||
set-env POWERLINE_COMMAND oh-my-posh
|
||||
|
||||
var _omp_error_code = 0
|
||||
var _omp_executable = ::OMP::
|
||||
var _omp_executable = (external ::OMP::)
|
||||
var _omp_status = 0
|
||||
var _omp_no_status = 1
|
||||
var _omp_execution_time = -1
|
||||
var _omp_terminal_width = ($_omp_executable get width)
|
||||
|
||||
fn _omp-after-readline-hook {|_|
|
||||
set _omp_execution_time = -1
|
||||
|
||||
# Getting the terminal width can fail inside a prompt function, so we do this here.
|
||||
set _omp_terminal_width = ($_omp_executable get width)
|
||||
}
|
||||
|
||||
fn _omp-after-command-hook {|m|
|
||||
# The command execution time should not be available in the first prompt.
|
||||
if (== $_omp_no_status 0) {
|
||||
set _omp_execution_time = (printf %.0f (* $m[duration] 1000))
|
||||
}
|
||||
|
||||
set _omp_no_status = 0
|
||||
|
||||
fn posh-after-command-hook {|m|
|
||||
var error = $m[error]
|
||||
if (is $error $nil) {
|
||||
set _omp_error_code = 0
|
||||
set _omp_status = 0
|
||||
} else {
|
||||
try {
|
||||
set _omp_error_code = $error[reason][exit-status]
|
||||
set _omp_status = $error[reason][exit-status]
|
||||
} catch {
|
||||
# built-in commands don't have a status code.
|
||||
set _omp_error_code = 1
|
||||
set _omp_status = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set edit:after-command = [ $@edit:after-command $posh-after-command-hook~ ]
|
||||
|
||||
set edit:prompt = {
|
||||
var cmd-duration = (printf "%.0f" (* $edit:command-duration 1000))
|
||||
(external $_omp_executable) print primary --shell=elvish --execution-time=$cmd-duration --status=$_omp_error_code --pwd=$pwd --shell-version=$E:POSH_SHELL_VERSION
|
||||
fn _omp_get_prompt {|type @arguments|
|
||||
$_omp_executable print $type ^
|
||||
--save-cache ^
|
||||
--shell=elvish ^
|
||||
--shell-version=$E:POSH_SHELL_VERSION ^
|
||||
--status=$_omp_status ^
|
||||
--no-status=$_omp_no_status ^
|
||||
--execution-time=$_omp_execution_time ^
|
||||
--terminal-width=$_omp_terminal_width ^
|
||||
$@arguments
|
||||
}
|
||||
|
||||
set edit:rprompt = {
|
||||
var cmd-duration = (printf "%.0f" (* $edit:command-duration 1000))
|
||||
(external $_omp_executable) print right --shell=elvish --execution-time=$cmd-duration --status=$_omp_error_code --pwd=$pwd --shell-version=$E:POSH_SHELL_VERSION
|
||||
}
|
||||
set edit:after-readline = [ $@edit:after-readline $_omp-after-readline-hook~ ]
|
||||
set edit:after-command = [ $@edit:after-command $_omp-after-command-hook~ ]
|
||||
set edit:prompt = {|| _omp_get_prompt primary }
|
||||
set edit:rprompt = {|| _omp_get_prompt right }
|
||||
|
|
|
@ -24,42 +24,58 @@ function set_poshcontext
|
|||
return
|
||||
end
|
||||
|
||||
function _omp_get_prompt
|
||||
if test (count $argv) -eq 0
|
||||
return
|
||||
end
|
||||
$_omp_executable print $argv[1] \
|
||||
--save-cache \
|
||||
--shell=fish \
|
||||
--shell-version=$FISH_VERSION \
|
||||
--status=$_omp_status \
|
||||
--pipestatus="$_omp_pipestatus" \
|
||||
--no-status=$_omp_no_status \
|
||||
--execution-time=$_omp_execution_time \
|
||||
--stack-count=$_omp_stack_count \
|
||||
$argv[2..]
|
||||
end
|
||||
|
||||
# NOTE: Input function calls via `commandline --function` are put into a queue and will not be executed until an outer regular function returns. See https://fishshell.com/docs/current/cmds/commandline.html.
|
||||
|
||||
function fish_prompt
|
||||
set --local omp_status_cache_temp $status
|
||||
set --local omp_pipestatus_cache_temp $pipestatus
|
||||
set --local omp_status_temp $status
|
||||
set --local omp_pipestatus_temp $pipestatus
|
||||
# clear from cursor to end of screen as
|
||||
# commandline --function repaint does not do this
|
||||
# see https://github.com/fish-shell/fish-shell/issues/8418
|
||||
printf \e\[0J
|
||||
if test "$_omp_transient" = 1
|
||||
$_omp_executable print transient --shell fish --status $_omp_status_cache --pipestatus="$_omp_pipestatus_cache" --execution-time $_omp_duration --stack-count $_omp_stack_count --shell-version $FISH_VERSION --no-status=$_omp_no_exit_code
|
||||
_omp_get_prompt transient
|
||||
return
|
||||
end
|
||||
if test "$_omp_new_prompt" = 0
|
||||
echo -n "$_omp_current_prompt"
|
||||
return
|
||||
end
|
||||
set --global _omp_status_cache $omp_status_cache_temp
|
||||
set --global _omp_pipestatus_cache $omp_pipestatus_cache_temp
|
||||
set --global _omp_status $omp_status_temp
|
||||
set --global _omp_pipestatus $omp_pipestatus_temp
|
||||
set --global _omp_no_status false
|
||||
set --global _omp_execution_time "$CMD_DURATION$cmd_duration"
|
||||
set --global _omp_stack_count (count $dirstack)
|
||||
set --global _omp_duration "$CMD_DURATION$cmd_duration"
|
||||
set --global _omp_no_exit_code false
|
||||
|
||||
# check if variable set, < 3.2 case
|
||||
if set --query _omp_last_command && test -z "$_omp_last_command"
|
||||
set _omp_duration 0
|
||||
set _omp_no_exit_code true
|
||||
set _omp_execution_time 0
|
||||
set _omp_no_status true
|
||||
end
|
||||
|
||||
# works with fish >=3.2
|
||||
if set --query _omp_last_status_generation && test "$_omp_last_status_generation" = "$status_generation"
|
||||
set _omp_duration 0
|
||||
set _omp_no_exit_code true
|
||||
set _omp_execution_time 0
|
||||
set _omp_no_status true
|
||||
else if test -z "$_omp_last_status_generation"
|
||||
# first execution - $status_generation is 0, $_omp_last_status_generation is empty
|
||||
set _omp_no_exit_code true
|
||||
set _omp_no_status true
|
||||
end
|
||||
|
||||
if set --query status_generation
|
||||
|
@ -81,7 +97,8 @@ function fish_prompt
|
|||
end
|
||||
|
||||
# The prompt is saved for possible reuse, typically a repaint after clearing the screen buffer.
|
||||
set --global _omp_current_prompt ($_omp_executable print primary --shell fish --status $_omp_status_cache --pipestatus="$_omp_pipestatus_cache" --execution-time $_omp_duration --stack-count $_omp_stack_count --shell-version $FISH_VERSION --cleared=$omp_cleared --no-status=$_omp_no_exit_code | string collect)
|
||||
set --global _omp_current_prompt (_omp_get_prompt primary --cleared=$omp_cleared | string join \n | string collect)
|
||||
|
||||
echo -n "$_omp_current_prompt"
|
||||
end
|
||||
|
||||
|
@ -98,7 +115,7 @@ function fish_right_prompt
|
|||
end
|
||||
|
||||
set _omp_new_prompt 0
|
||||
set --global _omp_current_rprompt ($_omp_executable print right --shell fish --status $_omp_status_cache --pipestatus="$_omp_pipestatus_cache" --execution-time $_omp_duration --stack-count $_omp_stack_count --shell-version $FISH_VERSION --no-status=$_omp_no_exit_code | string join '')
|
||||
set --global _omp_current_rprompt (_omp_get_prompt right | string join '')
|
||||
|
||||
echo -n "$_omp_current_rprompt"
|
||||
end
|
||||
|
@ -154,7 +171,7 @@ function _omp_space_key_handler
|
|||
end
|
||||
|
||||
set _omp_tooltip_command $tooltip_command
|
||||
set --local tooltip_prompt ($_omp_executable print tooltip --shell fish --status $_omp_status_cache --pipestatus="$_omp_pipestatus_cache" --execution-time $_omp_duration --stack-count $_omp_stack_count --shell-version $FISH_VERSION --command $_omp_tooltip_command --no-status=$_omp_no_exit_code | string join '')
|
||||
set --local tooltip_prompt (_omp_get_prompt tooltip --command=$_omp_tooltip_command | string join '')
|
||||
|
||||
if test -z "$tooltip_prompt"
|
||||
return
|
||||
|
|
|
@ -1,34 +1,24 @@
|
|||
-- Upgrade notice
|
||||
|
||||
local notice = [[::UPGRADENOTICE::]]
|
||||
|
||||
if '::UPGRADE::' == 'true' then
|
||||
print(notice)
|
||||
end
|
||||
---@diagnostic disable: undefined-global
|
||||
---@diagnostic disable: undefined-field
|
||||
---@diagnostic disable: lowercase-global
|
||||
|
||||
-- Cache PID
|
||||
os.setenv("POSH_PID", os.getpid())
|
||||
os.setenv('POSH_PID', os.getpid())
|
||||
|
||||
-- Helper functions
|
||||
|
||||
local function get_priority_number(name, default)
|
||||
local value = os.getenv(name)
|
||||
if os.envmap ~= nil and type(os.envmap) == 'table' then
|
||||
local t = os.envmap[name]
|
||||
value = (t ~= nil and type(t) == 'string') and t or value
|
||||
end
|
||||
if type(default) == 'number' then
|
||||
value = tonumber(value)
|
||||
if value == nil then
|
||||
return default
|
||||
else
|
||||
return value
|
||||
end
|
||||
else
|
||||
return default
|
||||
end
|
||||
local value = os.getenv(name)
|
||||
if value == nil and os.envmap ~= nil and type(os.envmap) == 'table' then
|
||||
value = os.envmap[name]
|
||||
end
|
||||
local num = tonumber(value)
|
||||
if num ~= nil then
|
||||
return num
|
||||
end
|
||||
return default
|
||||
end
|
||||
os.setenv("POSH_CURSOR_LINE", console.getnumlines())
|
||||
|
||||
-- Environment variables
|
||||
|
||||
local function environment_onbeginedit()
|
||||
|
@ -41,6 +31,7 @@ local endedit_time = 0
|
|||
local last_duration = 0
|
||||
local rprompt_enabled = false
|
||||
local transient_enabled = false
|
||||
local ftcs_marks_enabled = false
|
||||
local no_exit_code = true
|
||||
|
||||
local cached_prompt = {}
|
||||
|
@ -57,7 +48,7 @@ local function cache_onbeginedit()
|
|||
local old_cache = cached_prompt
|
||||
|
||||
-- Start a new table for the new edit/prompt session.
|
||||
cached_prompt = { cwd=cwd }
|
||||
cached_prompt = { cwd = cwd }
|
||||
|
||||
-- Copy the cached left/right prompt strings if the cwd hasn't changed.
|
||||
-- IMPORTANT OPTIMIZATION: This keeps the prompt highly responsive, except
|
||||
|
@ -68,33 +59,30 @@ local function cache_onbeginedit()
|
|||
end
|
||||
end
|
||||
|
||||
-- Executable
|
||||
|
||||
local omp_executable = '::OMP::'
|
||||
|
||||
-- Configuration
|
||||
|
||||
local function omp_exe()
|
||||
return '"'..::OMP::..'"'
|
||||
end
|
||||
|
||||
os.setenv("POSH_THEME", ::CONFIG::)
|
||||
os.setenv("POSH_SHELL_VERSION", string.format('clink v%s.%s.%s.%s', clink.version_major, clink.version_minor, clink.version_patch, clink.version_commit))
|
||||
os.setenv('POSH_THEME', '::CONFIG::')
|
||||
os.setenv('POSH_SHELL_VERSION', string.format('clink v%s.%s.%s.%s', clink.version_major, clink.version_minor, clink.version_patch, clink.version_commit))
|
||||
|
||||
-- Execution helpers
|
||||
|
||||
local function can_async()
|
||||
if (clink.version_encoded or 0) >= 10030001 then
|
||||
return settings.get("prompt.async")
|
||||
return settings.get('prompt.async')
|
||||
end
|
||||
end
|
||||
|
||||
local function run_posh_command(command)
|
||||
command = '"'..command..'"'
|
||||
local _, ismain = coroutine.running()
|
||||
local output
|
||||
if ismain then
|
||||
output = io.popen(command):read("*a")
|
||||
else
|
||||
output = io.popenyield(command):read("*a")
|
||||
command = string.format('""%s" %s"', omp_executable, command)
|
||||
local _, is_main = coroutine.running()
|
||||
if is_main then
|
||||
return io.popen(command):read('*a')
|
||||
end
|
||||
return output
|
||||
return io.popenyield(command):read('*a')
|
||||
end
|
||||
|
||||
-- Duration functions
|
||||
|
@ -105,10 +93,8 @@ local function os_clock_millis()
|
|||
-- OMP to get the time in milliseconds.
|
||||
if (clink.version_encoded or 0) >= 10020030 then
|
||||
return math.floor(os.clock() * 1000)
|
||||
else
|
||||
local prompt_exe = string.format('%s get millis --shell=cmd', omp_exe())
|
||||
return run_posh_command(prompt_exe)
|
||||
end
|
||||
return run_posh_command('get millis')
|
||||
end
|
||||
|
||||
local function duration_onbeginedit()
|
||||
|
@ -125,7 +111,7 @@ end
|
|||
local function duration_onendedit(input)
|
||||
endedit_time = 0
|
||||
-- For an empty command, the execution time should not be evaluated.
|
||||
if string.gsub(input, "^%s*(.-)%s*$", "%1") ~= "" then
|
||||
if string.gsub(input, '^%s*(.-)%s*$', '%1') ~= '' then
|
||||
endedit_time = os_clock_millis()
|
||||
end
|
||||
end
|
||||
|
@ -134,43 +120,48 @@ end
|
|||
|
||||
local function execution_time_option()
|
||||
if last_duration ~= nil then
|
||||
return "--execution-time "..last_duration
|
||||
return '--execution-time=' .. last_duration
|
||||
end
|
||||
return ""
|
||||
return ''
|
||||
end
|
||||
|
||||
local function error_level_option()
|
||||
if os.geterrorlevel ~= nil and settings.get("cmd.get_errorlevel") then
|
||||
return "--status "..os.geterrorlevel()
|
||||
local function status_option()
|
||||
if os.geterrorlevel ~= nil and settings.get('cmd.get_errorlevel') then
|
||||
return '--status=' .. os.geterrorlevel()
|
||||
end
|
||||
return ""
|
||||
return ''
|
||||
end
|
||||
|
||||
local function no_exit_code_option()
|
||||
local function no_status_option()
|
||||
if no_exit_code then
|
||||
return "--no-status"
|
||||
return '--no-status'
|
||||
end
|
||||
return ""
|
||||
return ''
|
||||
end
|
||||
|
||||
local function get_posh_prompt(rprompt)
|
||||
local prompt = "primary"
|
||||
if rprompt then
|
||||
prompt = "right"
|
||||
end
|
||||
local prompt_exe = string.format('%s print %s --shell=cmd %s %s %s', omp_exe(), prompt, execution_time_option(), error_level_option(), no_exit_code_option())
|
||||
return run_posh_command(prompt_exe)
|
||||
local function get_posh_prompt(prompt_type, ...)
|
||||
os.setenv('POSH_CURSOR_LINE', console.getnumlines())
|
||||
local command = table.concat({
|
||||
'print',
|
||||
prompt_type,
|
||||
'--save-cache',
|
||||
'--shell=cmd',
|
||||
status_option(),
|
||||
no_status_option(),
|
||||
execution_time_option(),
|
||||
...
|
||||
}, ' ')
|
||||
return run_posh_command(command)
|
||||
end
|
||||
|
||||
local function set_posh_tooltip(tip_command)
|
||||
if tip_command ~= "" and tip_command ~= cached_prompt.tip_command then
|
||||
if tip_command ~= '' and tip_command ~= cached_prompt.tip_command then
|
||||
-- Escape special characters properly, if any.
|
||||
local escaped_tip_command = string.gsub(tip_command, '(\\+)"', '%1%1"'):gsub('(\\+)$', '%1%1'):gsub('"', '\\"'):gsub('([&<>%(%)@%^|])', '^%1')
|
||||
|
||||
local prompt_exe = string.format('%s print tooltip --shell=cmd %s --command="%s"', omp_exe(), error_level_option(), escaped_tip_command)
|
||||
local tooltip = run_posh_command(prompt_exe)
|
||||
local escaped_tip_command = string.gsub(tip_command, '(\\+)"', '%1%1"'):gsub('(\\+)$', '%1%1'):gsub('"', '\\"'):gsub('([&<>%(%)@|%^])', '^%1'):gsub('%%', '%%%%')
|
||||
local command_option = string.format('--command "%s"', escaped_tip_command)
|
||||
local tooltip = get_posh_prompt('tooltip', command_option)
|
||||
-- Do not cache an empty tooltip.
|
||||
if tooltip == "" then
|
||||
if tooltip == '' then
|
||||
return
|
||||
end
|
||||
cached_prompt.tip_command = tip_command
|
||||
|
@ -185,25 +176,10 @@ local function display_cached_prompt()
|
|||
cached_prompt.only_use_cache = nil
|
||||
end
|
||||
|
||||
local function async_collect_posh_prompts()
|
||||
-- Generate the left prompt.
|
||||
cached_prompt.left = get_posh_prompt(false)
|
||||
|
||||
-- Generate the right prompt, if needed.
|
||||
if rprompt_enabled then
|
||||
display_cached_prompt() -- Show left side; don't wait for right side.
|
||||
cached_prompt.right = get_posh_prompt(true)
|
||||
end
|
||||
end
|
||||
|
||||
local function command_executed_mark(input)
|
||||
if string.gsub(input, "^%s*(.-)%s*$", "%1") ~= "" then
|
||||
no_exit_code = false
|
||||
else
|
||||
no_exit_code = true
|
||||
end
|
||||
if "::FTCS_MARKS::" == "true" then
|
||||
clink.print("\x1b]133;C\007", NONL)
|
||||
no_exit_code = string.gsub(input, '^%s*(.-)%s*$', '%1') == ''
|
||||
if ftcs_marks_enabled then
|
||||
clink.print('\x1b]133;C\007', NONL)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -216,7 +192,7 @@ function p:filter(prompt)
|
|||
|
||||
-- Get a left prompt immediately if nothing is available yet.
|
||||
if not cached_prompt.left then
|
||||
cached_prompt.left = get_posh_prompt(false)
|
||||
cached_prompt.left = get_posh_prompt('primary')
|
||||
need_left = false
|
||||
end
|
||||
|
||||
|
@ -228,10 +204,10 @@ function p:filter(prompt)
|
|||
-- function was defined. That way if a new prompt starts (which
|
||||
-- discards the old coroutine) and a new coroutine starts, the old
|
||||
-- coroutine won't stomp on the new cached_prompt table.
|
||||
clink.promptcoroutine(function ()
|
||||
clink.promptcoroutine(function()
|
||||
-- Generate left prompt, if needed.
|
||||
if need_left then
|
||||
cached_prompt.left = get_posh_prompt(false)
|
||||
cached_prompt.left = get_posh_prompt('primary')
|
||||
end
|
||||
-- Generate right prompt, if needed.
|
||||
if rprompt_enabled then
|
||||
|
@ -239,17 +215,17 @@ function p:filter(prompt)
|
|||
-- Show left side while right side is being generated.
|
||||
display_cached_prompt()
|
||||
end
|
||||
cached_prompt.right = get_posh_prompt(true)
|
||||
cached_prompt.right = get_posh_prompt('right')
|
||||
else
|
||||
cached_prompt.right = nil
|
||||
end
|
||||
end)
|
||||
else
|
||||
if need_left then
|
||||
cached_prompt.left = get_posh_prompt(false)
|
||||
cached_prompt.left = get_posh_prompt('primary')
|
||||
end
|
||||
if rprompt_enabled then
|
||||
cached_prompt.right = get_posh_prompt(true)
|
||||
cached_prompt.right = get_posh_prompt('right')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -269,10 +245,9 @@ function p:transientfilter(prompt)
|
|||
return nil
|
||||
end
|
||||
|
||||
local prompt_exe = string.format('%s print transient --shell=cmd %s %s', omp_exe(), error_level_option(), no_exit_code_option())
|
||||
prompt = run_posh_command(prompt_exe)
|
||||
prompt = get_posh_prompt('transient')
|
||||
|
||||
if prompt == "" then
|
||||
if prompt == '' then
|
||||
prompt = nil
|
||||
end
|
||||
|
||||
|
@ -280,7 +255,7 @@ function p:transientfilter(prompt)
|
|||
end
|
||||
|
||||
function p:transientrightfilter(prompt)
|
||||
return "", false
|
||||
return '', false
|
||||
end
|
||||
|
||||
-- Event handlers
|
||||
|
@ -303,12 +278,12 @@ end
|
|||
|
||||
-- Tooltips
|
||||
|
||||
function ohmyposh_space(rl_buffer)
|
||||
function _omp_space_keybinding(rl_buffer)
|
||||
-- Insert space first, in case it might affect the tip word, e.g. it could
|
||||
-- split "gitcommit" into "git commit".
|
||||
rl_buffer:insert(" ")
|
||||
rl_buffer:insert(' ')
|
||||
-- Get the first word of command line as tip.
|
||||
local tip_command = rl_buffer:getbuffer():gsub("^%s*([^%s]*).*$", "%1")
|
||||
local tip_command = rl_buffer:getbuffer():gsub('^%s*(.-)%s*$', '%1')
|
||||
|
||||
-- Generate a tooltip asynchronously (via coroutine) if available, otherwise
|
||||
-- generate a tooltip immediately.
|
||||
|
@ -318,7 +293,7 @@ function ohmyposh_space(rl_buffer)
|
|||
elseif cached_prompt.coroutine then
|
||||
-- No action needed; a tooltip coroutine is already running.
|
||||
else
|
||||
cached_prompt.coroutine = coroutine.create(function ()
|
||||
cached_prompt.coroutine = coroutine.create(function()
|
||||
set_posh_tooltip(tip_command)
|
||||
if cached_prompt.coroutine == coroutine.running() then
|
||||
cached_prompt.coroutine = nil
|
||||
|
@ -333,5 +308,5 @@ local function enable_tooltips()
|
|||
return
|
||||
end
|
||||
|
||||
rl.setbinding(' ', [["luafunc:ohmyposh_space"]], 'emacs')
|
||||
rl.setbinding(' ', [["luafunc:_omp_space_keybinding"]], 'emacs')
|
||||
end
|
||||
|
|
|
@ -4,28 +4,48 @@ if ($env.config? | is-not-empty) {
|
|||
}
|
||||
|
||||
$env.POWERLINE_COMMAND = 'oh-my-posh'
|
||||
$env.POSH_THEME = ::CONFIG::
|
||||
$env.POSH_THEME = (echo ::CONFIG::)
|
||||
$env.PROMPT_INDICATOR = ""
|
||||
$env.POSH_PID = (random uuid)
|
||||
$env.POSH_SHELL_VERSION = (version | get version)
|
||||
|
||||
let _omp_executable: string = ::OMP::
|
||||
|
||||
def posh_cmd_duration [] {
|
||||
# We have to do this because the initial value of `$env.CMD_DURATION_MS` is always `0823`,
|
||||
# which is an official setting.
|
||||
# See https://github.com/nushell/nushell/discussions/6402#discussioncomment-3466687.
|
||||
if $env.CMD_DURATION_MS == "0823" { 0 } else { $env.CMD_DURATION_MS }
|
||||
}
|
||||
|
||||
def posh_width [] {
|
||||
(term size).columns | into string
|
||||
}
|
||||
let _omp_executable: string = (echo ::OMP::)
|
||||
|
||||
# PROMPTS
|
||||
$env.PROMPT_MULTILINE_INDICATOR = (^$_omp_executable print secondary --shell=nu $"--shell-version=($env.POSH_SHELL_VERSION)")
|
||||
|
||||
$env.PROMPT_COMMAND = { ||
|
||||
def --wrapped _omp_get_prompt [
|
||||
type: string,
|
||||
...args: string
|
||||
] {
|
||||
mut execution_time = -1
|
||||
mut no_status = true
|
||||
# We have to do this because the initial value of `$env.CMD_DURATION_MS` is always `0823`, which is an official setting.
|
||||
# See https://github.com/nushell/nushell/discussions/6402#discussioncomment-3466687.
|
||||
if $env.CMD_DURATION_MS != '0823' {
|
||||
$execution_time = $env.CMD_DURATION_MS
|
||||
$no_status = false
|
||||
}
|
||||
|
||||
(
|
||||
^$_omp_executable print $type
|
||||
--save-cache
|
||||
--shell=nu
|
||||
$"--shell-version=($env.POSH_SHELL_VERSION)"
|
||||
$"--status=($env.LAST_EXIT_CODE)"
|
||||
$"--no-status=($no_status)"
|
||||
$"--execution-time=($execution_time)"
|
||||
$"--terminal-width=((term size).columns)"
|
||||
...$args
|
||||
)
|
||||
}
|
||||
|
||||
$env.PROMPT_MULTILINE_INDICATOR = (
|
||||
^$_omp_executable print secondary
|
||||
--shell=nu
|
||||
$"--shell-version=($env.POSH_SHELL_VERSION)"
|
||||
)
|
||||
|
||||
$env.PROMPT_COMMAND = {||
|
||||
# hack to set the cursor line to 1 when the user clears the screen
|
||||
# this obviously isn't bulletproof, but it's a start
|
||||
mut clear = false
|
||||
|
@ -37,9 +57,7 @@ $env.PROMPT_COMMAND = { ||
|
|||
do --env $env.SET_POSHCONTEXT
|
||||
}
|
||||
|
||||
^$_omp_executable print primary --shell=nu $"--shell-version=($env.POSH_SHELL_VERSION)" $"--execution-time=(posh_cmd_duration)" $"--status=($env.LAST_EXIT_CODE)" $"--terminal-width=(posh_width)" $"--cleared=($clear)"
|
||||
_omp_get_prompt primary $"--cleared=($clear)"
|
||||
}
|
||||
|
||||
$env.PROMPT_COMMAND_RIGHT = { ||
|
||||
^$_omp_executable print right --shell=nu $"--shell-version=($env.POSH_SHELL_VERSION)" $"--execution-time=(posh_cmd_duration)" $"--status=($env.LAST_EXIT_CODE)" $"--terminal-width=(posh_width)"
|
||||
}
|
||||
$env.PROMPT_COMMAND_RIGHT = {|| _omp_get_prompt right }
|
||||
|
|
|
@ -48,28 +48,24 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
|
|||
$env:POSH_THEME = (Resolve-Path -Path ::CONFIG::).ProviderPath
|
||||
}
|
||||
|
||||
function Start-Utf8Process {
|
||||
param(
|
||||
[string]$FileName,
|
||||
[string[]]$Arguments = @()
|
||||
)
|
||||
function Invoke-Utf8Posh {
|
||||
param([string[]]$Arguments = @())
|
||||
|
||||
if ($script:ConstrainedLanguageMode) {
|
||||
$standardOut = Invoke-Expression "& `$FileName `$Arguments 2>&1"
|
||||
$standardOut -join "`n"
|
||||
$output = Invoke-Expression "& `$global:_ompExecutable `$Arguments 2>&1"
|
||||
$output -join "`n"
|
||||
return
|
||||
}
|
||||
|
||||
$Process = New-Object System.Diagnostics.Process
|
||||
$StartInfo = $Process.StartInfo
|
||||
$StartInfo.FileName = $FileName
|
||||
$StartInfo.FileName = $global:_ompExecutable
|
||||
if ($StartInfo.ArgumentList.Add) {
|
||||
# ArgumentList is supported in PowerShell 6.1 and later (built on .NET Core 2.1+)
|
||||
# ref-1: https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics.processstartinfo.argumentlist?view=net-6.0
|
||||
# ref-2: https://docs.microsoft.com/en-us/powershell/scripting/whats-new/differences-from-windows-powershell?view=powershell-7.2#net-framework-vs-net-core
|
||||
$Arguments | ForEach-Object -Process { $StartInfo.ArgumentList.Add($_) }
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
# escape arguments manually in lower versions, refer to https://docs.microsoft.com/en-us/previous-versions/17w5ykft(v=vs.85)
|
||||
$escapedArgs = $Arguments | ForEach-Object {
|
||||
# escape N consecutive backslash(es), which are followed by a double quote, to 2N consecutive ones
|
||||
|
@ -113,8 +109,6 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
|
|||
$stdoutTask.Result
|
||||
}
|
||||
|
||||
function Set-PoshContext([bool]$originalStatus) {}
|
||||
|
||||
function Get-NonFSWD {
|
||||
# We only need to return a non-filesystem working directory.
|
||||
if ($PWD.Provider.Name -ne 'FileSystem') {
|
||||
|
@ -131,6 +125,192 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
|
|||
$terminalWidth
|
||||
}
|
||||
|
||||
function Get-FileHyperlink {
|
||||
param(
|
||||
[Parameter(Mandatory, ValuefromPipeline = $True)]
|
||||
[string]$Uri,
|
||||
[Parameter(ValuefromPipeline = $True)]
|
||||
[string]$Name
|
||||
)
|
||||
|
||||
if (!$Name) {
|
||||
# if name not set, uri is used as the name of the hyperlink
|
||||
$Name = $Uri
|
||||
}
|
||||
|
||||
if ($null -ne $env:WSL_DISTRO_NAME) {
|
||||
# wsl conversion if needed
|
||||
$Uri = &wslpath -m $Uri
|
||||
}
|
||||
|
||||
# return an ANSI formatted hyperlink
|
||||
return "`e]8;;file://$Uri`e\$Name`e]8;;`e\"
|
||||
}
|
||||
|
||||
function Set-TransientPrompt {
|
||||
$previousOutputEncoding = [Console]::OutputEncoding
|
||||
try {
|
||||
$script:TransientPrompt = $true
|
||||
[Console]::OutputEncoding = [Text.Encoding]::UTF8
|
||||
[Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt()
|
||||
} finally {
|
||||
[Console]::OutputEncoding = $previousOutputEncoding
|
||||
}
|
||||
}
|
||||
|
||||
function Set-PoshPromptType {
|
||||
if ($script:TransientPrompt -eq $true) {
|
||||
$script:PromptType = "transient"
|
||||
$script:TransientPrompt = $false
|
||||
return
|
||||
}
|
||||
|
||||
# for details about the trick to detect a debugging context, see these comments:
|
||||
# 1) https://github.com/JanDeDobbeleer/oh-my-posh/issues/2483#issuecomment-1175761456
|
||||
# 2) https://github.com/JanDeDobbeleer/oh-my-posh/issues/2502#issuecomment-1179968052
|
||||
# 3) https://github.com/JanDeDobbeleer/oh-my-posh/issues/5153
|
||||
if ($Host.Runspace.Debugger.InBreakpoint) {
|
||||
$script:PromptType = "debug"
|
||||
return
|
||||
}
|
||||
|
||||
$script:PromptType = "primary"
|
||||
|
||||
if ($global:_ompJobCount) {
|
||||
$script:JobCount = (Get-Job -State Running).Count
|
||||
}
|
||||
|
||||
if ($global:_ompAzure) {
|
||||
try {
|
||||
$env:POSH_AZURE_SUBSCRIPTION = Get-AzContext | ConvertTo-Json
|
||||
} catch {}
|
||||
}
|
||||
|
||||
if ($global:_ompPoshGit) {
|
||||
try {
|
||||
$global:GitStatus = Get-GitStatus
|
||||
$env:POSH_GIT_STATUS = $global:GitStatus | ConvertTo-Json
|
||||
} catch {}
|
||||
}
|
||||
}
|
||||
|
||||
function Update-PoshErrorCode {
|
||||
$lastHistory = Get-History -ErrorAction Ignore -Count 1
|
||||
|
||||
# error code should be updated only when a non-empty command is run
|
||||
if (($null -eq $lastHistory) -or ($script:LastHistoryId -eq $lastHistory.Id)) {
|
||||
$script:ExecutionTime = 0
|
||||
$script:NoExitCode = $true
|
||||
return
|
||||
}
|
||||
|
||||
$script:NoExitCode = $false
|
||||
$script:LastHistoryId = $lastHistory.Id
|
||||
$script:ExecutionTime = ($lastHistory.EndExecutionTime - $lastHistory.StartExecutionTime).TotalMilliseconds
|
||||
if ($script:OriginalLastExecutionStatus) {
|
||||
$script:ErrorCode = 0
|
||||
return
|
||||
}
|
||||
|
||||
$invocationInfo = try {
|
||||
# retrieve info of the most recent error
|
||||
$global:Error[0] | Where-Object { $_ -ne $null } | Select-Object -ExpandProperty InvocationInfo
|
||||
} catch { $null }
|
||||
|
||||
# check if the last command caused the last error
|
||||
if ($null -ne $invocationInfo -and $lastHistory.CommandLine -eq $invocationInfo.Line) {
|
||||
$script:ErrorCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
if ($script:OriginalLastExitCode -is [int] -and $script:OriginalLastExitCode -ne 0) {
|
||||
# native app exit code
|
||||
$script:ErrorCode = $script:OriginalLastExitCode
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
function Get-PoshPrompt {
|
||||
param(
|
||||
[string]$Type,
|
||||
[string[]]$Arguments
|
||||
)
|
||||
$nonFSWD = Get-NonFSWD
|
||||
$stackCount = Get-PoshStackCount
|
||||
$terminalWidth = Get-TerminalWidth
|
||||
Invoke-Utf8Posh @(
|
||||
"print", $Type
|
||||
"--save-cache"
|
||||
"--shell=$script:ShellName"
|
||||
"--shell-version=$script:PSVersion"
|
||||
"--status=$script:ErrorCode"
|
||||
"--no-status=$script:NoExitCode"
|
||||
"--execution-time=$script:ExecutionTime"
|
||||
"--pswd=$nonFSWD"
|
||||
"--stack-count=$stackCount"
|
||||
"--terminal-width=$terminalWidth"
|
||||
"--job-count=$script:JobCount"
|
||||
if ($Arguments) { $Arguments }
|
||||
)
|
||||
}
|
||||
|
||||
$promptFunction = {
|
||||
# store the orignal last command execution status
|
||||
if ($global:NVS_ORIGINAL_LASTEXECUTIONSTATUS -is [bool]) {
|
||||
# make it compatible with NVS auto-switching, if enabled
|
||||
$script:OriginalLastExecutionStatus = $global:NVS_ORIGINAL_LASTEXECUTIONSTATUS
|
||||
} else {
|
||||
$script:OriginalLastExecutionStatus = $?
|
||||
}
|
||||
# store the orignal last exit code
|
||||
$script:OriginalLastExitCode = $global:LASTEXITCODE
|
||||
|
||||
Set-PoshPromptType
|
||||
|
||||
if ($script:PromptType -ne 'transient') {
|
||||
Update-PoshErrorCode
|
||||
}
|
||||
|
||||
Set-PoshContext $script:ErrorCode
|
||||
|
||||
# set the cursor positions, they are zero based so align with other platforms
|
||||
$env:POSH_CURSOR_LINE = $Host.UI.RawUI.CursorPosition.Y + 1
|
||||
$env:POSH_CURSOR_COLUMN = $Host.UI.RawUI.CursorPosition.X + 1
|
||||
|
||||
$output = Get-PoshPrompt $script:PromptType
|
||||
# make sure PSReadLine knows if we have a multiline prompt
|
||||
Set-PSReadLineOption -ExtraPromptLineCount (($output | Measure-Object -Line).Lines - 1)
|
||||
|
||||
# The output can be multi-line, joining them ensures proper rendering.
|
||||
$output = $output -join "`n"
|
||||
|
||||
if ($script:PromptType -eq 'transient') {
|
||||
# Workaround to prevent a command from eating the tail of a transient prompt, when we're at the end of the line.
|
||||
$command = ''
|
||||
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$command, [ref]$null)
|
||||
if ($command) {
|
||||
$output += " `b`b"
|
||||
}
|
||||
}
|
||||
|
||||
$output
|
||||
|
||||
# remove any posh-git status
|
||||
$env:POSH_GIT_STATUS = $null
|
||||
|
||||
# restore the orignal last exit code
|
||||
$global:LASTEXITCODE = $script:OriginalLastExitCode
|
||||
}
|
||||
|
||||
$Function:prompt = $promptFunction
|
||||
|
||||
# set secondary prompt
|
||||
Set-PSReadLineOption -ContinuationPrompt ((Invoke-Utf8Posh @("print", "secondary", "--shell=$script:ShellName")) -join "`n")
|
||||
|
||||
### Exported Functions ###
|
||||
|
||||
function Set-PoshContext([bool]$originalStatus) {}
|
||||
|
||||
function Enable-PoshTooltips {
|
||||
if ($script:ConstrainedLanguageMode) {
|
||||
return
|
||||
|
@ -151,35 +331,21 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
|
|||
}
|
||||
|
||||
$script:TooltipCommand = $command
|
||||
$column = $Host.UI.RawUI.CursorPosition.X
|
||||
$terminalWidth = Get-TerminalWidth
|
||||
$nonFSWD = Get-NonFSWD
|
||||
$stackCount = global:Get-PoshStackCount
|
||||
|
||||
$standardOut = (Start-Utf8Process $global:_ompExecutable @("print", "tooltip", "--status=$script:ErrorCode", "--shell=$script:ShellName", "--pswd=$nonFSWD", "--execution-time=$script:ExecutionTime", "--stack-count=$stackCount", "--command=$command", "--shell-version=$script:PSVersion", "--column=$column", "--terminal-width=$terminalWidth", "--no-status=$script:NoExitCode", "--job-count=$script:JobCount")) -join ''
|
||||
if (!$standardOut) {
|
||||
$output = (Get-PoshPrompt "tooltip" @(
|
||||
"--column=$($Host.UI.RawUI.CursorPosition.X)"
|
||||
"--command=$command"
|
||||
)) -join ''
|
||||
if (!$output) {
|
||||
return
|
||||
}
|
||||
|
||||
Write-Host $standardOut -NoNewline
|
||||
Write-Host $output -NoNewline
|
||||
|
||||
# Workaround to prevent the text after cursor from disappearing when the tooltip is printed.
|
||||
[Microsoft.PowerShell.PSConsoleReadLine]::Insert(' ')
|
||||
[Microsoft.PowerShell.PSConsoleReadLine]::Undo()
|
||||
}
|
||||
finally {}
|
||||
}
|
||||
}
|
||||
|
||||
function Set-TransientPrompt {
|
||||
$previousOutputEncoding = [Console]::OutputEncoding
|
||||
try {
|
||||
$script:TransientPrompt = $true
|
||||
[Console]::OutputEncoding = [Text.Encoding]::UTF8
|
||||
[Microsoft.PowerShell.PSConsoleReadLine]::InvokePrompt()
|
||||
}
|
||||
finally {
|
||||
[Console]::OutputEncoding = $previousOutputEncoding
|
||||
} finally {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,8 +363,7 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
|
|||
$script:TooltipCommand = ''
|
||||
Set-TransientPrompt
|
||||
}
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
[Microsoft.PowerShell.PSConsoleReadLine]::AcceptLine()
|
||||
if ($global:_ompFTCSMarks -and $executingCommand) {
|
||||
# Write FTCS_COMMAND_EXECUTED after accepting the input - it should still happen before execution
|
||||
|
@ -216,16 +381,15 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
|
|||
$script:TooltipCommand = ''
|
||||
Set-TransientPrompt
|
||||
}
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
[Microsoft.PowerShell.PSConsoleReadLine]::CopyOrCancelLine()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Enable-PoshLineError {
|
||||
$validLine = (Start-Utf8Process $global:_ompExecutable @("print", "valid", "--shell=$script:ShellName")) -join "`n"
|
||||
$errorLine = (Start-Utf8Process $global:_ompExecutable @("print", "error", "--shell=$script:ShellName")) -join "`n"
|
||||
$validLine = (Invoke-Utf8Posh @("print", "valid", "--shell=$script:ShellName")) -join "`n"
|
||||
$errorLine = (Invoke-Utf8Posh @("print", "error", "--shell=$script:ShellName")) -join "`n"
|
||||
Set-PSReadLineOption -PromptText $validLine, $errorLine
|
||||
}
|
||||
|
||||
|
@ -264,40 +428,24 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
|
|||
$Format = 'json'
|
||||
)
|
||||
|
||||
$configString = Start-Utf8Process $global:_ompExecutable @("config", "export", "--format=$Format")
|
||||
# if no path, copy to clipboard by default
|
||||
if ($FilePath) {
|
||||
# https://stackoverflow.com/questions/3038337/powershell-resolve-path-that-might-not-exist
|
||||
$FilePath = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($FilePath)
|
||||
[IO.File]::WriteAllLines($FilePath, $configString)
|
||||
}
|
||||
else {
|
||||
Set-Clipboard $configString
|
||||
Write-Output "Theme copied to clipboard"
|
||||
}
|
||||
}
|
||||
|
||||
function Get-FileHyperlink {
|
||||
param(
|
||||
[Parameter(Mandatory, ValuefromPipeline = $True)]
|
||||
[string]$uri,
|
||||
[Parameter(ValuefromPipeline = $True)]
|
||||
[string]$name
|
||||
$output = Invoke-Utf8Posh @(
|
||||
"config", "export"
|
||||
"--format=$Format"
|
||||
"--output=$FilePath"
|
||||
)
|
||||
|
||||
$esc = [char]27
|
||||
if (!$name) {
|
||||
# if name not set, uri is used as the name of the hyperlink
|
||||
$name = $uri
|
||||
if (!$output) {
|
||||
Write-Host "Theme exported to $(Get-FileHyperlink $FilePath)."
|
||||
return
|
||||
}
|
||||
|
||||
if ($null -ne $env:WSL_DISTRO_NAME) {
|
||||
# wsl conversion if needed
|
||||
$uri = &wslpath -m $uri
|
||||
}
|
||||
|
||||
# return an ANSI formatted hyperlink
|
||||
return "$esc]8;;file://$uri$esc\$name$esc]8;;$esc\"
|
||||
# When no path is provided, copy the output to clipboard.
|
||||
Set-Clipboard $output
|
||||
Write-Host 'Theme copied to clipboard.'
|
||||
}
|
||||
|
||||
function Get-PoshThemes {
|
||||
|
@ -329,19 +477,28 @@ New-Module -Name "oh-my-posh-core" -ScriptBlock {
|
|||
Write-Host $logo
|
||||
$themes = Get-ChildItem -Path "$Path/*" -Include '*.omp.json' | Sort-Object Name
|
||||
if ($List -eq $true) {
|
||||
$themes | Select-Object @{ Name = 'hyperlink'; Expression = { Get-FileHyperlink -uri $_.FullName } } | Format-Table -HideTableHeaders
|
||||
}
|
||||
else {
|
||||
$themes | Select-Object @{ Name = 'hyperlink'; Expression = { Get-FileHyperlink -Uri $_.FullName } } | Format-Table -HideTableHeaders
|
||||
} else {
|
||||
$nonFSWD = Get-NonFSWD
|
||||
$stackCount = Get-PoshStackCount
|
||||
$terminalWidth = Get-TerminalWidth
|
||||
$themes | ForEach-Object -Process {
|
||||
Write-Host "Theme: $(Get-FileHyperlink -uri $_.FullName -Name ($_.BaseName -replace '\.omp$', ''))`n"
|
||||
Start-Utf8Process $global:_ompExecutable @("print", "primary", "--config=$($_.FullName)", "--pswd=$nonFSWD", "--shell=$script:ShellName")
|
||||
Write-Host "Theme: $(Get-FileHyperlink -Uri $_.FullName -Name ($_.BaseName -replace '\.omp$', ''))`n"
|
||||
Invoke-Utf8Posh @(
|
||||
"print", "primary"
|
||||
"--config=$($_.FullName)"
|
||||
"--shell=$script:ShellName"
|
||||
"--shell-version=$script:PSVersion"
|
||||
"--pswd=$nonFSWD"
|
||||
"--stack-count=$stackCount"
|
||||
"--terminal-width=$terminalWidth"
|
||||
)
|
||||
Write-Host "`n"
|
||||
}
|
||||
}
|
||||
Write-Host @"
|
||||
|
||||
Themes location: $(Get-FileHyperlink -uri "$Path")
|
||||
Themes location: $(Get-FileHyperlink -Uri "$Path")
|
||||
|
||||
To change your theme, adjust the init script in $PROFILE.
|
||||
Example:
|
||||
|
@ -350,139 +507,6 @@ Example:
|
|||
"@
|
||||
}
|
||||
|
||||
function Set-PoshPromptType {
|
||||
if ($script:TransientPrompt -eq $true) {
|
||||
$script:PromptType = "transient"
|
||||
$script:TransientPrompt = $false
|
||||
return
|
||||
}
|
||||
|
||||
# for details about the trick to detect a debugging context, see these comments:
|
||||
# 1) https://github.com/JanDeDobbeleer/oh-my-posh/issues/2483#issuecomment-1175761456
|
||||
# 2) https://github.com/JanDeDobbeleer/oh-my-posh/issues/2502#issuecomment-1179968052
|
||||
# 3) https://github.com/JanDeDobbeleer/oh-my-posh/issues/5153
|
||||
if ($Host.Runspace.Debugger.InBreakpoint) {
|
||||
$script:PromptType = "debug"
|
||||
return
|
||||
}
|
||||
|
||||
$script:PromptType = "primary"
|
||||
|
||||
if ($global:_ompJobCount) {
|
||||
$script:JobCount = (Get-Job -State Running).Count
|
||||
}
|
||||
|
||||
if ($global:_ompAzure) {
|
||||
try {
|
||||
$env:POSH_AZURE_SUBSCRIPTION = Get-AzContext | ConvertTo-Json
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
|
||||
if ($global:_ompPoshGit) {
|
||||
try {
|
||||
$global:GitStatus = Get-GitStatus
|
||||
$env:POSH_GIT_STATUS = $global:GitStatus | ConvertTo-Json
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
}
|
||||
|
||||
function Update-PoshErrorCode {
|
||||
$lastHistory = Get-History -ErrorAction Ignore -Count 1
|
||||
|
||||
# error code should be updated only when a non-empty command is run
|
||||
if (($null -eq $lastHistory) -or ($script:LastHistoryId -eq $lastHistory.Id)) {
|
||||
$script:ExecutionTime = 0
|
||||
$script:NoExitCode = $true
|
||||
return
|
||||
}
|
||||
|
||||
$script:NoExitCode = $false
|
||||
$script:LastHistoryId = $lastHistory.Id
|
||||
$script:ExecutionTime = ($lastHistory.EndExecutionTime - $lastHistory.StartExecutionTime).TotalMilliseconds
|
||||
if ($script:OriginalLastExecutionStatus) {
|
||||
$script:ErrorCode = 0
|
||||
return
|
||||
}
|
||||
|
||||
$invocationInfo = try {
|
||||
# retrieve info of the most recent error
|
||||
$global:Error[0] | Where-Object { $_ -ne $null } | Select-Object -ExpandProperty InvocationInfo
|
||||
}
|
||||
catch { $null }
|
||||
|
||||
# check if the last command caused the last error
|
||||
if ($null -ne $invocationInfo -and $lastHistory.CommandLine -eq $invocationInfo.Line) {
|
||||
$script:ErrorCode = 1
|
||||
return
|
||||
}
|
||||
|
||||
if ($script:OriginalLastExitCode -is [int] -and $script:OriginalLastExitCode -ne 0) {
|
||||
# native app exit code
|
||||
$script:ErrorCode = $script:OriginalLastExitCode
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
$promptFunction = {
|
||||
# store the orignal last command execution status
|
||||
if ($global:NVS_ORIGINAL_LASTEXECUTIONSTATUS -is [bool]) {
|
||||
# make it compatible with NVS auto-switching, if enabled
|
||||
$script:OriginalLastExecutionStatus = $global:NVS_ORIGINAL_LASTEXECUTIONSTATUS
|
||||
}
|
||||
else {
|
||||
$script:OriginalLastExecutionStatus = $?
|
||||
}
|
||||
# store the orignal last exit code
|
||||
$script:OriginalLastExitCode = $global:LASTEXITCODE
|
||||
|
||||
Set-PoshPromptType
|
||||
|
||||
if ($script:PromptType -ne 'transient') {
|
||||
Update-PoshErrorCode
|
||||
}
|
||||
|
||||
Set-PoshContext $script:ErrorCode
|
||||
|
||||
$nonFSWD = Get-NonFSWD
|
||||
$stackCount = global:Get-PoshStackCount
|
||||
$terminalWidth = Get-TerminalWidth
|
||||
|
||||
# set the cursor positions, they are zero based so align with other platforms
|
||||
$env:POSH_CURSOR_LINE = $Host.UI.RawUI.CursorPosition.Y + 1
|
||||
$env:POSH_CURSOR_COLUMN = $Host.UI.RawUI.CursorPosition.X + 1
|
||||
|
||||
$standardOut = Start-Utf8Process $global:_ompExecutable @("print", $script:PromptType, "--status=$script:ErrorCode", "--pswd=$nonFSWD", "--execution-time=$script:ExecutionTime", "--stack-count=$stackCount", "--shell-version=$script:PSVersion", "--terminal-width=$terminalWidth", "--shell=$script:ShellName", "--no-status=$script:NoExitCode", "--job-count=$script:JobCount")
|
||||
# make sure PSReadLine knows if we have a multiline prompt
|
||||
Set-PSReadLineOption -ExtraPromptLineCount (($standardOut | Measure-Object -Line).Lines - 1)
|
||||
|
||||
# The output can be multi-line, joining them ensures proper rendering.
|
||||
$output = $standardOut -join "`n"
|
||||
|
||||
if ($script:PromptType -eq 'transient') {
|
||||
# Workaround to prevent a command from eating the tail of a transient prompt, when we're at the end of the line.
|
||||
$command = ''
|
||||
[Microsoft.PowerShell.PSConsoleReadLine]::GetBufferState([ref]$command, [ref]$null)
|
||||
if ($command) {
|
||||
$output += " `b`b"
|
||||
}
|
||||
}
|
||||
|
||||
$output
|
||||
|
||||
# remove any posh-git status
|
||||
$env:POSH_GIT_STATUS = $null
|
||||
|
||||
# restore the orignal last exit code
|
||||
$global:LASTEXITCODE = $script:OriginalLastExitCode
|
||||
}
|
||||
|
||||
$Function:prompt = $promptFunction
|
||||
|
||||
# set secondary prompt
|
||||
Set-PSReadLineOption -ContinuationPrompt ((Start-Utf8Process $global:_ompExecutable @("print", "secondary", "--shell=$script:ShellName")) -join "`n")
|
||||
|
||||
# perform cleanup on removal so a new initialization in current session works
|
||||
if (!$script:ConstrainedLanguageMode) {
|
||||
$ExecutionContext.SessionState.Module.OnRemove += {
|
||||
|
@ -506,11 +530,6 @@ Example:
|
|||
}
|
||||
}
|
||||
|
||||
$notice = Start-Utf8Process $global:_ompExecutable @("notice")
|
||||
if ($notice) {
|
||||
Write-Host $notice -NoNewline
|
||||
}
|
||||
|
||||
Export-ModuleMember -Function @(
|
||||
"Set-PoshContext"
|
||||
"Enable-PoshTooltips"
|
||||
|
@ -518,7 +537,6 @@ Example:
|
|||
"Enable-PoshLineError"
|
||||
"Export-PoshTheme"
|
||||
"Get-PoshThemes"
|
||||
"Start-Utf8Process"
|
||||
"prompt"
|
||||
)
|
||||
} | Import-Module -Global
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
import uuid
|
||||
|
||||
$POWERLINE_COMMAND = "oh-my-posh"
|
||||
$POSH_THEME = r"::CONFIG::"
|
||||
$POSH_PID = uuid.uuid4().hex
|
||||
$POSH_SHELL_VERSION = $XONSH_VERSION
|
||||
$POSH_EXECUTABLE = r"::OMP::"
|
||||
|
||||
def get_command_context():
|
||||
last_cmd = __xonsh__.history[-1] if __xonsh__.history else None
|
||||
status = last_cmd.rtn if last_cmd else 0
|
||||
duration = round((last_cmd.ts[1] - last_cmd.ts[0]) * 1000) if last_cmd else 0
|
||||
return status, duration
|
||||
|
||||
def posh_primary():
|
||||
status, duration = get_command_context()
|
||||
return $(@($POSH_EXECUTABLE) print primary --shell=xonsh --status=@(status) --execution-time=@(duration) --shell-version=@($POSH_SHELL_VERSION))
|
||||
|
||||
def posh_right():
|
||||
status, duration = get_command_context()
|
||||
return $(@($POSH_EXECUTABLE) print right --shell=xonsh --status=@(status) --execution-time=@(duration) --shell-version=@($POSH_SHELL_VERSION))
|
||||
|
||||
|
||||
$PROMPT = posh_primary
|
||||
$RIGHT_PROMPT = posh_right
|
|
@ -1,20 +1,34 @@
|
|||
setenv POWERLINE_COMMAND "oh-my-posh";
|
||||
setenv POSH_THEME ::CONFIG::;
|
||||
setenv POSH_SHELL_VERSION "";
|
||||
setenv POSH_SHELL_VERSION "$tcsh";
|
||||
setenv POSH_PID $$;
|
||||
setenv OSTYPE "$OSTYPE";
|
||||
|
||||
if ("$OSTYPE" =~ {msys,cygwin}*) then
|
||||
setenv POSH_PID "`cat /proc/$$/winpid`";
|
||||
endif
|
||||
if ( "$OSTYPE" =~ {msys,cygwin}* ) setenv POSH_PID "`cat /proc/$$/winpid`";
|
||||
|
||||
set POSH_COMMAND = ::OMP::;
|
||||
set USER_PRECMD = "`alias precmd`";
|
||||
set USER_POSTCMD = "`alias postcmd`";
|
||||
set POSH_PRECMD = 'set POSH_CMD_STATUS = $status;set POSH_END_TIME = `$POSH_COMMAND get millis`;set POSH_DURATION = 0;if ( $POSH_START_TIME != -1 ) @ POSH_DURATION = $POSH_END_TIME - $POSH_START_TIME;set prompt = "`$POSH_COMMAND print primary --shell=tcsh --status=$POSH_CMD_STATUS --execution-time=$POSH_DURATION`";set POSH_START_TIME = -1';
|
||||
set POSH_POSTCMD = 'set POSH_START_TIME = `$POSH_COMMAND get millis`';
|
||||
if ( ! $?_omp_enabled ) alias precmd '
|
||||
set _omp_status = $status;
|
||||
set _omp_execution_time = -1;
|
||||
set _omp_last_cmd = `echo $_:q`;
|
||||
if ( $#_omp_last_cmd && $?_omp_cmd_executed ) @ _omp_execution_time = `"$_omp_executable" get millis` - $_omp_start_time;
|
||||
unset _omp_last_cmd;
|
||||
unset _omp_cmd_executed;
|
||||
@ _omp_stack_count = $#dirstack - 1;
|
||||
set prompt = "`$_omp_executable:q print primary
|
||||
--save-cache
|
||||
--shell=tcsh
|
||||
--shell-version=$tcsh
|
||||
--status=$_omp_status
|
||||
--execution-time=$_omp_execution_time
|
||||
--stack-count=$_omp_stack_count`";
|
||||
'"`alias precmd`";
|
||||
|
||||
alias precmd "$POSH_PRECMD;$USER_PRECMD";
|
||||
alias postcmd "$POSH_POSTCMD;$USER_POSTCMD";
|
||||
if ( ! $?_omp_enabled ) alias postcmd '
|
||||
set _omp_start_time = `"$_omp_executable" get millis`;
|
||||
set _omp_cmd_executed;
|
||||
'"`alias postcmd`";
|
||||
|
||||
set POSH_START_TIME = `$POSH_COMMAND get millis`;
|
||||
set _omp_enabled;
|
||||
set _omp_executable = ::OMP::;
|
||||
set _omp_execution_time = -1;
|
||||
set _omp_start_time = -1;
|
||||
|
|
49
src/shell/scripts/omp.xsh
Normal file
49
src/shell/scripts/omp.xsh
Normal file
|
@ -0,0 +1,49 @@
|
|||
import uuid
|
||||
|
||||
$POWERLINE_COMMAND = "oh-my-posh"
|
||||
$POSH_THEME = ::CONFIG::
|
||||
$POSH_PID = uuid.uuid4().hex
|
||||
$POSH_SHELL_VERSION = $XONSH_VERSION
|
||||
|
||||
_omp_executable = ::OMP::
|
||||
_omp_history_length = 0
|
||||
|
||||
def _omp_get_context():
|
||||
global _omp_history_length
|
||||
status = 0
|
||||
duration = -1
|
||||
|
||||
if __xonsh__.history:
|
||||
last_cmd = __xonsh__.history[-1]
|
||||
if last_cmd:
|
||||
status = last_cmd.rtn
|
||||
|
||||
history_length = len(__xonsh__.history)
|
||||
if history_length != _omp_history_length:
|
||||
_omp_history_length = history_length
|
||||
duration = round((last_cmd.ts[1] - last_cmd.ts[0]) * 1000)
|
||||
|
||||
return status, duration
|
||||
|
||||
def _omp_get_prompt(type: str, *args: str):
|
||||
status, duration = _omp_get_context()
|
||||
return $(
|
||||
@(_omp_executable) print @(type) \
|
||||
--save-cache \
|
||||
--shell=xonsh \
|
||||
--shell-version=$XONSH_VERSION \
|
||||
--status=@(status) \
|
||||
--execution-time=@(duration) \
|
||||
@(args)
|
||||
)
|
||||
|
||||
def _omp_get_primary():
|
||||
return _omp_get_prompt('primary')
|
||||
|
||||
def _omp_get_right():
|
||||
return _omp_get_prompt('right')
|
||||
|
||||
$PROMPT = _omp_get_primary
|
||||
# When the primary prompt has multiple lines, the right prompt is always displayed on the first line, which is inconsistent with other supported shells.
|
||||
# The behavior is controlled by Xonsh, and there is no way to change it.
|
||||
$RIGHT_PROMPT = _omp_get_right
|
|
@ -1,9 +1,8 @@
|
|||
export POSH_THEME=::CONFIG::
|
||||
export POSH_SHELL_VERSION=$ZSH_VERSION
|
||||
export POSH_PID=$$
|
||||
export POWERLINE_COMMAND="oh-my-posh"
|
||||
export POWERLINE_COMMAND='oh-my-posh'
|
||||
export CONDA_PROMPT_MODIFIER=false
|
||||
export POSH_PROMPT_COUNT=0
|
||||
export ZLE_RPROMPT_INDENT=0
|
||||
export OSTYPE=$OSTYPE
|
||||
|
||||
|
@ -12,6 +11,7 @@ if [[ $OSTYPE =~ ^(msys|cygwin) ]]; then
|
|||
fi
|
||||
|
||||
_omp_executable=::OMP::
|
||||
_omp_tooltip_command=''
|
||||
|
||||
# switches to enable/disable features
|
||||
_omp_cursor_positioning=0
|
||||
|
@ -31,7 +31,7 @@ function _omp_set_cursor_position() {
|
|||
stty raw -echo min 0
|
||||
|
||||
local pos
|
||||
echo -en "\033[6n" >/dev/tty
|
||||
echo -en '\033[6n' >/dev/tty
|
||||
read -r -d R pos
|
||||
pos=${pos:2} # strip off the esc-[
|
||||
local parts=(${(s:;:)pos})
|
||||
|
@ -49,32 +49,30 @@ function set_poshcontext() {
|
|||
|
||||
function _omp_preexec() {
|
||||
if [[ $_omp_ftcs_marks == 0 ]]; then
|
||||
printf "\033]133;C\007"
|
||||
printf '\033]133;C\007'
|
||||
fi
|
||||
|
||||
_omp_start_time=$($_omp_executable get millis)
|
||||
}
|
||||
|
||||
function _omp_precmd() {
|
||||
_omp_status_cache=$?
|
||||
_omp_pipestatus_cache=(${pipestatus[@]})
|
||||
_omp_status=$?
|
||||
_omp_pipestatus=(${pipestatus[@]})
|
||||
_omp_stack_count=${#dirstack[@]}
|
||||
_omp_elapsed=-1
|
||||
_omp_no_exit_code="true"
|
||||
_omp_execution_time=-1
|
||||
_omp_no_status=true
|
||||
_omp_tooltip_command=''
|
||||
|
||||
if [ $_omp_start_time ]; then
|
||||
local omp_now=$($_omp_executable get millis --shell=zsh)
|
||||
_omp_elapsed=$(($omp_now - $_omp_start_time))
|
||||
_omp_no_exit_code="false"
|
||||
local omp_now=$($_omp_executable get millis)
|
||||
_omp_execution_time=$(($omp_now - $_omp_start_time))
|
||||
_omp_no_status=false
|
||||
fi
|
||||
|
||||
if [[ ${_omp_pipestatus_cache[-1]} != "$_omp_status_cache" ]]; then
|
||||
_omp_pipestatus_cache=("$_omp_status_cache")
|
||||
if [[ ${_omp_pipestatus[-1]} != "$_omp_status" ]]; then
|
||||
_omp_pipestatus=("$_omp_status")
|
||||
fi
|
||||
|
||||
count=$((POSH_PROMPT_COUNT + 1))
|
||||
export POSH_PROMPT_COUNT=$count
|
||||
|
||||
set_poshcontext
|
||||
_omp_set_cursor_position
|
||||
|
||||
|
@ -86,8 +84,8 @@ function _omp_precmd() {
|
|||
setopt PROMPT_PERCENT
|
||||
|
||||
PS2=$_omp_secondary_prompt
|
||||
eval "$(_omp_get_prompt primary --eval)"
|
||||
|
||||
eval "$($_omp_executable print primary --status="$_omp_status_cache" --pipestatus="${_omp_pipestatus_cache[*]}" --execution-time="$_omp_elapsed" --stack-count="$_omp_stack_count" --eval --shell=zsh --shell-version="$ZSH_VERSION" --no-status="$_omp_no_exit_code")"
|
||||
unset _omp_start_time
|
||||
}
|
||||
|
||||
|
@ -116,6 +114,21 @@ function _omp_cleanup() {
|
|||
_omp_cleanup
|
||||
unset -f _omp_cleanup
|
||||
|
||||
function _omp_get_prompt() {
|
||||
local type=$1
|
||||
local args=("${@[2,-1]}")
|
||||
$_omp_executable print $type \
|
||||
--save-cache \
|
||||
--shell=zsh \
|
||||
--shell-version=$ZSH_VERSION \
|
||||
--status=$_omp_status \
|
||||
--pipestatus="${_omp_pipestatus[*]}" \
|
||||
--no-status=$_omp_no_status \
|
||||
--execution-time=$_omp_execution_time \
|
||||
--stack-count=$_omp_stack_count \
|
||||
${args[@]}
|
||||
}
|
||||
|
||||
function _omp_render_tooltip() {
|
||||
if [[ $KEYS != ' ' ]]; then
|
||||
return
|
||||
|
@ -130,7 +143,7 @@ function _omp_render_tooltip() {
|
|||
fi
|
||||
|
||||
_omp_tooltip_command="$tooltip_command"
|
||||
local tooltip=$($_omp_executable print tooltip --status="$_omp_status_cache" --pipestatus="${_omp_pipestatus_cache[*]}" --execution-time="$_omp_elapsed" --stack-count="$_omp_stack_count" --command="$tooltip_command" --shell=zsh --shell-version="$ZSH_VERSION" --no-status="$_omp_no_exit_code")
|
||||
local tooltip=$(_omp_get_prompt tooltip --command="$tooltip_command")
|
||||
if [[ -z $tooltip ]]; then
|
||||
return
|
||||
fi
|
||||
|
@ -148,23 +161,21 @@ function _omp_zle-line-init() {
|
|||
local -i ret=$?
|
||||
(( $+zle_bracketed_paste )) && print -r -n - $zle_bracketed_paste[2]
|
||||
|
||||
_omp_tooltip_command=''
|
||||
eval "$($_omp_executable print transient --status="$_omp_status_cache" --pipestatus="${_omp_pipestatus_cache[*]}" --execution-time="$_omp_elapsed" --stack-count="$_omp_stack_count" --eval --shell=zsh --shell-version="$ZSH_VERSION" --no-status="$_omp_no_exit_code")"
|
||||
eval "$(_omp_get_prompt transient --eval)"
|
||||
zle .reset-prompt
|
||||
|
||||
# Exit the shell if we receive EOT.
|
||||
if [[ $ret == 0 && $KEYS == $'\4' ]]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
if ((ret)); then
|
||||
# TODO (fix): this is not equal to sending a SIGINT, since the status code ($?) is set to 1 instead of 130.
|
||||
zle .send-break
|
||||
else
|
||||
# Enter
|
||||
zle .accept-line
|
||||
fi
|
||||
return ret
|
||||
|
||||
# Exit the shell if we receive EOT.
|
||||
if [[ $KEYS == $'\4' ]]; then
|
||||
exit
|
||||
fi
|
||||
|
||||
zle .accept-line
|
||||
return $ret
|
||||
}
|
||||
|
||||
# Helper function for calling a widget before the specified OMP function.
|
||||
|
@ -205,7 +216,7 @@ function _omp_create_widget() {
|
|||
}
|
||||
|
||||
function enable_poshtooltips() {
|
||||
local widget=${$(bindkey " "):2}
|
||||
local widget=${$(bindkey ' '):2}
|
||||
|
||||
if [[ -z $widget ]]; then
|
||||
widget=self-insert
|
||||
|
|
|
@ -2,6 +2,8 @@ package shell
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//go:embed scripts/omp.tcsh
|
||||
|
@ -10,12 +12,23 @@ var tcshInit string
|
|||
func (f Feature) Tcsh() Code {
|
||||
switch f {
|
||||
case Upgrade:
|
||||
return "$POSH_COMMAND upgrade;"
|
||||
return `"$_omp_executable" upgrade;`
|
||||
case Notice:
|
||||
return "$POSH_COMMAND notice;"
|
||||
return `"$_omp_executable" notice;`
|
||||
case PromptMark, RPrompt, PoshGit, Azure, LineError, Jobs, Tooltips, Transient, FTCSMarks, CursorPositioning:
|
||||
fallthrough
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func quoteCshStr(str string) string {
|
||||
if len(str) == 0 {
|
||||
return "''"
|
||||
}
|
||||
|
||||
// An non-working edge case: there is no way to preserve a newline ('\n') in command substitution.
|
||||
// Therefore, we can only get a limited string without newlines for "eval".
|
||||
return fmt.Sprintf("'%s'", strings.NewReplacer("'", `'"'"'`,
|
||||
"!", `\!`).Replace(str))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -10,8 +11,22 @@ func TestTcshFeatures(t *testing.T) {
|
|||
got := allFeatures.Lines(TCSH).String("// these are the features")
|
||||
|
||||
want := `// these are the features
|
||||
$POSH_COMMAND upgrade;
|
||||
$POSH_COMMAND notice;`
|
||||
"$_omp_executable" upgrade;
|
||||
"$_omp_executable" notice;`
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestQuoteCshStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: "", expected: "''"},
|
||||
{str: `/tmp/"omp's dir"!/oh-my-posh`, expected: `'/tmp/"omp'"'"'s dir"\!/oh-my-posh'`},
|
||||
{str: `C:/tmp\omp's dir/oh-my-posh.exe`, expected: `'C:/tmp\omp'"'"'s dir/oh-my-posh.exe'`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, quoteCshStr(tc.str), fmt.Sprintf("quoteCshStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,20 +2,34 @@ package shell
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
//go:embed scripts/omp.py
|
||||
//go:embed scripts/omp.xsh
|
||||
var xonshInit string
|
||||
|
||||
func (f Feature) Xonsh() Code {
|
||||
switch f {
|
||||
case Upgrade:
|
||||
return "@($POSH_EXECUTABLE) upgrade"
|
||||
return "@(_omp_executable) upgrade"
|
||||
case Notice:
|
||||
return "@($POSH_EXECUTABLE) notice"
|
||||
return "@(_omp_executable) notice"
|
||||
case PromptMark, RPrompt, PoshGit, Azure, LineError, Jobs, Tooltips, Transient, CursorPositioning, FTCSMarks:
|
||||
fallthrough
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func quotePythonStr(str string) string {
|
||||
if len(str) == 0 {
|
||||
return "''"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("'%s'", strings.NewReplacer(
|
||||
"'", `'"'"'`,
|
||||
`\`, `\\`,
|
||||
"\n", `\n`,
|
||||
).Replace(str))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package shell
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -10,8 +11,22 @@ func TestXonshFeatures(t *testing.T) {
|
|||
got := allFeatures.Lines(XONSH).String("// these are the features")
|
||||
|
||||
want := `// these are the features
|
||||
@($POSH_EXECUTABLE) upgrade
|
||||
@($POSH_EXECUTABLE) notice`
|
||||
@(_omp_executable) upgrade
|
||||
@(_omp_executable) notice`
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
}
|
||||
|
||||
func TestQuotePythonStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
str string
|
||||
expected string
|
||||
}{
|
||||
{str: "", expected: "''"},
|
||||
{str: `/tmp/"omp's dir"/oh-my-posh`, expected: `'/tmp/"omp'"'"'s dir"/oh-my-posh'`},
|
||||
{str: `C:/tmp\omp's dir/oh-my-posh.exe`, expected: `'C:/tmp\\omp'"'"'s dir/oh-my-posh.exe'`},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
assert.Equal(t, tc.expected, quotePythonStr(tc.str), fmt.Sprintf("quotePythonStr: %s", tc.str))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,21 +7,16 @@ import (
|
|||
//go:embed scripts/omp.zsh
|
||||
var zshInit string
|
||||
|
||||
const (
|
||||
unixUpgrade = "$_omp_executable upgrade"
|
||||
unixNotice = "$_omp_executable notice"
|
||||
)
|
||||
|
||||
func (f Feature) Zsh() Code {
|
||||
switch f {
|
||||
case CursorPositioning:
|
||||
return "_omp_cursor_positioning=1"
|
||||
return unixCursorPositioning
|
||||
case Tooltips:
|
||||
return "enable_poshtooltips"
|
||||
case Transient:
|
||||
return "_omp_create_widget zle-line-init _omp_zle-line-init"
|
||||
case FTCSMarks:
|
||||
return "_omp_ftcs_marks=1"
|
||||
return unixFTCSMarks
|
||||
case Upgrade:
|
||||
return unixUpgrade
|
||||
case Notice:
|
||||
|
|
|
@ -13,8 +13,8 @@ func TestZshFeatures(t *testing.T) {
|
|||
enable_poshtooltips
|
||||
_omp_create_widget zle-line-init _omp_zle-line-init
|
||||
_omp_ftcs_marks=1
|
||||
$_omp_executable upgrade
|
||||
$_omp_executable notice
|
||||
"$_omp_executable" upgrade
|
||||
"$_omp_executable" notice
|
||||
_omp_cursor_positioning=1`
|
||||
|
||||
assert.Equal(t, want, got)
|
||||
|
|
|
@ -183,34 +183,29 @@ func ClearAfter() string {
|
|||
}
|
||||
|
||||
func FormatTitle(title string) string {
|
||||
switch Shell {
|
||||
// These shells don't support setting the console title.
|
||||
if Shell == shell.ELVISH || Shell == shell.XONSH {
|
||||
case shell.ELVISH, shell.XONSH, shell.TCSH:
|
||||
return ""
|
||||
}
|
||||
case shell.BASH, shell.ZSH:
|
||||
title = trimAnsi(title)
|
||||
s := new(strings.Builder)
|
||||
|
||||
title = trimAnsi(title)
|
||||
// We have to do this to prevent the shell from misidentifying escape sequences.
|
||||
for _, char := range title {
|
||||
escaped, shouldEscape := formats.EscapeSequences[char]
|
||||
if shouldEscape {
|
||||
s.WriteString(escaped)
|
||||
continue
|
||||
}
|
||||
|
||||
if Plain {
|
||||
return title
|
||||
}
|
||||
|
||||
if Shell != shell.BASH && Shell != shell.ZSH {
|
||||
return fmt.Sprintf(formats.Title, title)
|
||||
}
|
||||
|
||||
// We have to do this to prevent Bash/Zsh from misidentifying escape sequences.
|
||||
s := new(strings.Builder)
|
||||
for _, char := range title {
|
||||
escaped, shouldEscape := formats.EscapeSequences[char]
|
||||
if shouldEscape {
|
||||
s.WriteString(escaped)
|
||||
continue
|
||||
s.WriteRune(char)
|
||||
}
|
||||
|
||||
s.WriteRune(char)
|
||||
return fmt.Sprintf(formats.Title, s.String())
|
||||
default:
|
||||
return fmt.Sprintf(formats.Title, trimAnsi(title))
|
||||
}
|
||||
|
||||
return fmt.Sprintf(formats.Title, s.String())
|
||||
}
|
||||
|
||||
func EscapeText(text string) string {
|
||||
|
|
|
@ -47,6 +47,7 @@ func Latest(env runtime.Environment) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var release release
|
||||
// this can't fail
|
||||
_ = json.Unmarshal(body, &release)
|
||||
|
|
|
@ -188,10 +188,10 @@ to only require remote scripts to be signed using `Set-ExecutionPolicy RemoteSig
|
|||
Adjust the Oh My Posh init line in `~/.tcshrc` by adding the `--config` flag with the location of your configuration.
|
||||
|
||||
```bash
|
||||
eval `oh-my-posh init tcsh --config ~/jandedobbeleer.omp.json`
|
||||
eval "`oh-my-posh init tcsh --config ~/jandedobbeleer.omp.json`"
|
||||
```
|
||||
|
||||
Once added, reload your profile for the changes to take effect.
|
||||
Note that the surrounding quotes are required. Once added, reload your profile for the changes to take effect.
|
||||
|
||||
```bash
|
||||
exec tcsh
|
||||
|
|
|
@ -183,10 +183,10 @@ Once added, reload your profile for the changes to take effect.
|
|||
Add the following at the end of `~/.tcshrc`:
|
||||
|
||||
```bash
|
||||
eval `oh-my-posh init tcsh`
|
||||
eval "`oh-my-posh init tcsh`"
|
||||
```
|
||||
|
||||
Once added, reload your profile for the changes to take effect.
|
||||
Note that the surrounding quotes are required. Once added, reload your profile for the changes to take effect.
|
||||
|
||||
```bash
|
||||
exec tcsh
|
||||
|
|
Loading…
Reference in a new issue