2
3
Fork 0
Browse Source

Rewrites prompt generation to avoid multiple string traversals and adds file globbing as a part of parsing

master
sloum 1 year ago
parent
commit
64f8d9c31e
  1. 1
      .gitignore
  2. 36
      commandRunner.go
  3. 70
      main.go
  4. 27
      utils.go

1
.gitignore vendored

@ -1,2 +1,3 @@
slosh
slosh_*
roadmap.md

36
commandRunner.go

@ -5,6 +5,7 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"strconv"
"strings"
"unicode"
@ -212,18 +213,7 @@ func (cl *CommandLine) ExpandVars() {
}
}
func (cl *CommandLine) ExpandPaths() {
for i := range cl.value {
if cl.value[i].kind == sysPath {
cl.value[i].value = ExpandedAbsFilepath(cl.value[i].value)
}
}
}
func (cl CommandLine) Command() *exec.Cmd {
// Expand all of the paths before calling
cl.ExpandPaths()
// Expand all variables
cl.ExpandVars()
@ -306,6 +296,18 @@ func ParseCommandLine(ln string) (CommandSession, []string) {
} else {
if val, ok := alias[ce.value]; ok && ce.kind == comElement {
comLine.value = append(comLine.value, val.value...)
} else if ce.kind == sysPath {
ce.value = ExpandedAbsFilepath(ce.value)
ce.value = os.ExpandEnv(ce.value)
globs, e := filepath.Glob(ce.value)
if e != nil {
comLine.value = append(comLine.value, ce)
}
globCESlice := make([]CommandElement, len(globs))
for i := range globs {
globCESlice[i] = CommandElement{sysPath, globs[i]}
}
comLine.value = append(comLine.value, globCESlice...)
} else {
comLine.value = append(comLine.value, ce)
}
@ -390,6 +392,18 @@ func ParseCommandLine(ln string) (CommandSession, []string) {
} else {
if val, ok := alias[ce.value]; ok && ce.kind == comElement {
comLine.value = append(comLine.value, val.value...)
} else if ce.kind == sysPath {
ce.value = ExpandedAbsFilepath(ce.value)
ce.value = os.ExpandEnv(ce.value)
globs, e := filepath.Glob(ce.value)
if e != nil {
comLine.value = append(comLine.value, ce)
}
globCESlice := make([]CommandElement, len(globs))
for i := range globs {
globCESlice[i] = CommandElement{sysPath, globs[i]}
}
comLine.value = append(comLine.value, globCESlice...)
} else {
comLine.value = append(comLine.value, ce)
}

70
main.go

@ -6,7 +6,6 @@ import (
"io/ioutil"
"os"
"os/signal"
"os/user"
"path/filepath"
"strings"
"syscall"
@ -29,6 +28,7 @@ var (
initialTerm ln.ModeApplier = nil
linerTerm ln.ModeApplier = nil
currentMode int = 0
Hostname string
)
func setUpLineInput() *ln.State {
@ -127,7 +127,7 @@ func setCompletionNames() {
}
func prompt(ln *ln.State) string {
val, err := ln.Prompt(get_slosh_prompt())
val, err := ln.Prompt(getSloshPrompt())
if err != nil {
panic("Input read error")
}
@ -135,35 +135,59 @@ func prompt(ln *ln.State) string {
return val
}
func get_slosh_prompt() string {
func getSloshPrompt() string {
p := os.Getenv("SLOSH_PROMPT")
wd, _ := os.Getwd()
if p == "" {
return wd + "# "
return wd + " # "
}
short := wd
if strings.Contains(p, "%d") {
s := strings.Split(short, "/")
if len(s) > 3 {
short = fmt.Sprintf("...%s", filepath.Join(s[len(s)-3:]...))
var prev rune = 0
var out strings.Builder
for _, c := range []rune(p) {
if c == '%' {
prev = c
} else if prev == '%' {
out.WriteString(promptReplace(c, wd))
prev = c
} else {
out.WriteRune(c)
prev = c
}
}
p = strings.ReplaceAll(p, "%D", wd)
p = strings.ReplaceAll(p, "%d", short)
p = strings.ReplaceAll(p, "%c", filepath.Base(wd))
u, err := user.Current()
if err != nil {
p = strings.ReplaceAll(p, "%u", "???")
} else {
p = strings.ReplaceAll(p, "%u", u.Name)
}
p = strings.ReplaceAll(p, "\\n", "\n")
p = strings.ReplaceAll(p, "\\r", "\r")
return p
return out.String()
}
// func get_slosh_prompt() string {
// p := os.Getenv("SLOSH_PROMPT")
// wd, _ := os.Getwd()
// if p == "" {
// return wd + " # "
// }
// short := wd
// if strings.Contains(p, "%d") {
// s := strings.Split(short, "/")
// if len(s) > 3 {
// short = fmt.Sprintf("...%s", filepath.Join(s[len(s)-3:]...))
// }
// }
// p = strings.ReplaceAll(p, "%D", wd)
// p = strings.ReplaceAll(p, "%d", short)
// p = strings.ReplaceAll(p, "%h", Hostname)
// p = strings.ReplaceAll(p, "%c", filepath.Base(wd))
// u, err := user.Current()
// if err != nil || u.Name == "" {
// u.Name = os.Getenv("USER")
// p = strings.ReplaceAll(p, "%u", u.Name)
// } else {
// p = strings.ReplaceAll(p, "%u", u.Name)
// }
//
// return p
// }
func initShell() *ln.State {
Hostname, _ = os.Hostname()
setCompletionNames()
ParseSloshFile()
return setUpLineInput()
@ -173,9 +197,9 @@ func handleSignals(c <-chan os.Signal) {
for {
switch <-c {
case syscall.SIGTSTP:
//do nothing
// Do nothing
case syscall.SIGINT:
os.Exit(3)
// Do nothing
}
}
}

27
utils.go

@ -2,6 +2,7 @@ package main
import (
"bytes"
"fmt"
"io"
"os"
"os/exec"
@ -132,3 +133,29 @@ func call(stack []*exec.Cmd, pipes []*io.PipeWriter) (err error) {
os.Setenv("?", strconv.Itoa(stack[0].ProcessState.ExitCode()))
return e
}
func promptReplace(c rune, wd string) string {
switch c {
case 'u':
u, err := user.Current()
if err != nil || u.Name == "" {
return os.Getenv("USER")
} else {
return u.Name
}
case 'c':
return filepath.Base(wd)
case 'D':
return wd
case 'd':
s := strings.Split(wd, "/")
if len(s) > 4 {
return fmt.Sprintf("...%s", filepath.Join(s[len(s)-3:]...))
} else {
return wd
}
case 'h':
return Hostname
}
return fmt.Sprintf("%%%c", c)
}

Loading…
Cancel
Save