Skip to content

Commit 167e2d7

Browse files
committed
update
0 parents  commit 167e2d7

File tree

8 files changed

+693
-0
lines changed

8 files changed

+693
-0
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.idea
2+
.vscode

Makefile

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
MKFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
2+
CURRENT_DIR := $(patsubst %/,%,$(dir $(MKFILE_PATH)))
3+
4+
ZSH_PROMPT_SETUP_SCRIPT := $(CURRENT_DIR)/zsh/prompt_goprompt_setup.zsh
5+
6+
install:
7+
go install ./cmd/goprompt
8+
9+
prompt.source:
10+
@echo ". $(ZSH_PROMPT_SETUP_SCRIPT)"
11+
12+
try: install
13+
ZSH_DISABLE_PROMPT=Y ZSH_EXTRA_SOURCE="$(ZSH_PROMPT_SETUP_SCRIPT)" zsh

cmd/goprompt/main.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"github.com/codeskyblue/go-sh"
7+
"github.com/spf13/cobra"
8+
"github.com/spf13/pflag"
9+
"os"
10+
"strings"
11+
"sync"
12+
)
13+
14+
type CobraCallbackE func(cmd *cobra.Command, args []string) error
15+
16+
var (
17+
cmd = &cobra.Command{
18+
Use: "goprompt",
19+
PersistentPreRunE: bindEnvironmentFlags("GOPROMPT"),
20+
}
21+
cmdQuery = &cobra.Command{
22+
Use: "query",
23+
RunE: cmdQueryExec,
24+
}
25+
26+
cmdQueryStatus = cmd.PersistentFlags().Int(
27+
"cmd-status", 0,
28+
"cmd status of previous command",
29+
)
30+
cmdQueryPreexecTS = cmd.PersistentFlags().String(
31+
"preexec-ts", "0",
32+
"pre-execution timestamp to gauge how log execution took",
33+
)
34+
)
35+
36+
func init() {
37+
cmd.AddCommand(cmdQuery)
38+
39+
}
40+
41+
func bindEnvironmentFlags(prefix string) CobraCallbackE {
42+
return func(cmd *cobra.Command, args []string) (outErr error) {
43+
cmd.Flags().VisitAll(func(f *pflag.Flag) {
44+
if !f.Changed {
45+
envKey := prefix + "_" + strings.ReplaceAll(f.Name, "-", "_")
46+
if value, ok := os.LookupEnv(strings.ToUpper(envKey)); ok {
47+
if err := cmd.Flags().Set(f.Name, value); err != nil {
48+
outErr = err
49+
return
50+
}
51+
}
52+
}
53+
})
54+
return nil
55+
}
56+
}
57+
58+
func cmdQueryExec(cmd *cobra.Command, args []string) error {
59+
if *cmdQueryStatus != 0 {
60+
printPart("st", fmt.Sprintf("%#v", *cmdQueryStatus))
61+
}
62+
63+
wg := new(sync.WaitGroup)
64+
65+
wg.Add(1)
66+
go func() {
67+
defer wg.Done()
68+
69+
if wd, err := os.Getwd(); err == nil {
70+
printPart("wd", trimPathLast(wd, 2))
71+
}
72+
}()
73+
74+
wg.Add(1)
75+
go func() {
76+
defer wg.Done()
77+
78+
if branch, err := sh.Command("git", "branch", "--show-current").Output(); err == nil {
79+
printPart("git_br", trim(string(branch)))
80+
}
81+
}()
82+
83+
wg.Add(1)
84+
go func() {
85+
defer wg.Done()
86+
87+
if status, err := sh.Command("git", "status", "--porcelain").Output(); err == nil {
88+
if len(status) > 0 {
89+
printPart("git_st", "dirty")
90+
} else {
91+
printPart("git_st", "clean")
92+
}
93+
}
94+
}()
95+
96+
wg.Wait()
97+
return nil
98+
}
99+
100+
func trimPathLast(s string, n int) string {
101+
return s
102+
}
103+
104+
func intMax(a, b int) int {
105+
if a > b {
106+
return a
107+
} else {
108+
return b
109+
}
110+
}
111+
112+
func trim(s string) string {
113+
return strings.Trim(s, "\n\t ")
114+
}
115+
116+
func printPart(name string, value interface{}) {
117+
if _, err := os.Stdout.Stat(); err != nil {
118+
os.Exit(1)
119+
}
120+
fmt.Printf("%s\t%v\n", name, value)
121+
}
122+
123+
// PROMPT PARTS:
124+
// (exit-status: if > 0)
125+
// (parent-process)
126+
// (hostname: if remote connection)
127+
// (current-dir-path)
128+
// (vsc-information)
129+
// (timestamp)
130+
131+
func main() {
132+
err := cmd.ExecuteContext(context.Background())
133+
if err != nil {
134+
panic(err)
135+
}
136+
}

go.mod

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module EXP
2+
3+
go 1.14
4+
5+
require (
6+
github.com/codeskyblue/go-sh v0.0.0-20200712050446-30169cf553fe
7+
github.com/spf13/cobra v1.1.1
8+
github.com/spf13/pflag v1.0.5
9+
)

go.sum

Lines changed: 290 additions & 0 deletions
Large diffs are not rendered by default.

zsh/prompt_goprompt_setup.bak.zsh

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# In a file `prompt_goprompt_setup` available on `fpath`:
2+
3+
typeset -g GOPROMPT_NEWLINE=$'\n%{\r%}'
4+
5+
#-------------------------------------------------------------------------------
6+
7+
autoload -Uz add-zsh-hook
8+
9+
#-------------------------------------------------------------------------------
10+
11+
__goprompt_update_handler() {
12+
local BR=$GOPROMPT_NEWLINE
13+
local -a prompt_parts=(
14+
":: ${(j.:.)GOPROMPT_PARTS}"
15+
"# "
16+
)
17+
18+
PROMPT="$BR${(pj.$BR.)prompt_parts}"
19+
zle && zle .reset-prompt
20+
}
21+
22+
__goprompt_async_handler() {
23+
local ZLE_FD=$1
24+
25+
if ! IFS= read -r ASYNC_RESULT <&"$ZLE_FD"; then
26+
# select marks this fd if we reach EOF,
27+
# so handle this specially.
28+
__zle_async_detach "$ZLE_FD"
29+
return 1
30+
fi
31+
32+
GOPROMPT_PARTS+=( "$ASYNC_RESULT" )
33+
__goprompt_update_handler
34+
}
35+
36+
__goprompt_preexec() {
37+
typeset -g GOPROMPT_PREEXEC_TS=$EPOCHSECONDS
38+
}
39+
40+
__goprompt_precmd() {
41+
GOPROMPT_PARTS=()
42+
__goprompt_update_handler
43+
__zle_async_dispatch __goprompt_async_handler \
44+
__goprompt_run query \
45+
--cmd-status $? \
46+
--preexec-ts "$GOPROMPT_PREEXEC_TS"
47+
}
48+
49+
#-------------------------------------------------------------------------------
50+
# ZLE Async
51+
#-------------------------------------------------------------------------------
52+
53+
declare -A ZLE_ASYNC_FDS=()
54+
55+
__zle_async_dispatch() {
56+
local dispatch_handler="$1"; shift 1
57+
local command=( "$@" )
58+
59+
# Close existing file descriptor for this handler.
60+
local OLD_ZLE_FD=${ZLE_ASYNC_FDS["${dispatch_handler}"]}
61+
if [[ -n $OLD_ZLE_FD ]]; then
62+
__zle_async_detach "$OLD_ZLE_FD" 2>/dev/null
63+
fi
64+
65+
# Create File Descriptor and attach to async command
66+
exec {ZLE_FD}< <( "${command[@]}" )
67+
68+
# Attach file a ZLE handler to file descriptor.
69+
zle -F $ZLE_FD "${dispatch_handler}"
70+
ZLE_ASYNC_FDS["${dispatch_handler}"]="$ZLE_FD"
71+
}
72+
73+
__zle_async_detach() {
74+
local ZLE_FD=$1
75+
# Close stdout.
76+
exec {ZLE_FD}<&-
77+
# Close the file-descriptor.
78+
zle -F "$ZLE_FD"
79+
}
80+
81+
#-------------------------------------------------------------------------------
82+
83+
__goprompt_run() {
84+
if ! (( $+commands[goprompt] )); then
85+
echo -n "[ERROR: goprompt binary missing]"
86+
fi
87+
goprompt "$@"
88+
}
89+
90+
91+
prompt_goprompt_setup() {
92+
add-zsh-hook precmd __goprompt_precmd
93+
add-zsh-hook preexec __goprompt_preexec
94+
}
95+
96+
prompt_goprompt_setup "$@"

zsh/prompt_goprompt_setup.zsh

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# In a file `prompt_goprompt_setup` available on `fpath`:
2+
3+
typeset -g GOPROMPT_NEWLINE=$'\n%{\r%}'
4+
5+
typeset -g GOPROMPT_LAST_STATUS=0
6+
typeset -g GOPROMPT_PREEXEC_TS=0
7+
8+
typeset -gA GOPROMPT_PARTS=()
9+
10+
#-------------------------------------------------------------------------------
11+
12+
autoload -Uz add-zsh-hook
13+
14+
#-------------------------------------------------------------------------------
15+
16+
__goprompt_update_handler() {
17+
local BR=$GOPROMPT_NEWLINE
18+
local -A P=( "${(@kv)GOPROMPT_PARTS}" )
19+
20+
local GOPROMPT_PARTS_BOTTOM=()
21+
local GOPROMPT_PARTS_TOP=()
22+
23+
local -a prompt_parts=(
24+
":: (git: ${P[git_st]})"
25+
":: ${P[wd]}"
26+
"# "
27+
)
28+
29+
PROMPT="$BR${(pj.$BR.)prompt_parts}"
30+
zle && zle reset-prompt
31+
}
32+
33+
__goprompt_async_handler() {
34+
local ZLE_FD=$1
35+
36+
if ! IFS=$'\n' read -r ASYNC_RESULT <&"$ZLE_FD"; then
37+
# select marks this fd if we reach EOF,
38+
# so handle this specially.
39+
__zle_async_detach "$ZLE_FD"
40+
return 1
41+
fi
42+
43+
# split by tab char
44+
local KV=( "${(@s/ /)ASYNC_RESULT}" )
45+
46+
GOPROMPT_PARTS[${KV[1]}]=${KV[2]}
47+
48+
__goprompt_update_handler
49+
}
50+
51+
__goprompt_preexec() {
52+
typeset -g GOPROMPT_PREEXEC_TS=$EPOCHSECONDS
53+
}
54+
55+
__goprompt_precmd() {
56+
GOPROMPT_LAST_STATUS=$?
57+
GOPROMPT_PARTS=()
58+
59+
__goprompt_update_handler
60+
__zle_async_dispatch __goprompt_async_handler \
61+
__goprompt_run query \
62+
--cmd-status "$GOPROMPT_LAST_STATUS" \
63+
--preexec-ts "$GOPROMPT_PREEXEC_TS"
64+
}
65+
66+
#-------------------------------------------------------------------------------
67+
# ZLE Async
68+
#-------------------------------------------------------------------------------
69+
70+
declare -A ZLE_ASYNC_FDS=()
71+
72+
__zle_async_dispatch() {
73+
local dispatch_handler="$1"; shift 1
74+
local command=( "$@" )
75+
76+
# Close existing file descriptor for this handler.
77+
local OLD_ZLE_FD=${ZLE_ASYNC_FDS["${dispatch_handler}"]}
78+
if [[ -n $OLD_ZLE_FD ]]; then
79+
__zle_async_detach "$OLD_ZLE_FD" 2>/dev/null
80+
fi
81+
82+
# Create File Descriptor and attach to async command
83+
exec {ZLE_FD}< <( "${command[@]}" )
84+
85+
# Attach file a ZLE handler to file descriptor.
86+
zle -F $ZLE_FD "${dispatch_handler}"
87+
ZLE_ASYNC_FDS["${dispatch_handler}"]="$ZLE_FD"
88+
}
89+
90+
__zle_async_detach() {
91+
local ZLE_FD=$1
92+
# Close stdout.
93+
exec {ZLE_FD}<&-
94+
# Close the file-descriptor.
95+
zle -F "$ZLE_FD"
96+
}
97+
98+
#-------------------------------------------------------------------------------
99+
100+
__goprompt_run() {
101+
if ! (( $+commands[goprompt] )); then
102+
echo -n "[ERROR: goprompt binary missing]"
103+
fi
104+
goprompt "$@"
105+
}
106+
107+
108+
prompt_goprompt_setup() {
109+
add-zsh-hook precmd __goprompt_precmd
110+
add-zsh-hook preexec __goprompt_preexec
111+
}
112+
113+
prompt_goprompt_setup "$@"

0 commit comments

Comments
 (0)