draft of arrow bindings

add session history dispatch
extend reshctl
add recall - both command and handler for the daemon
add session_init
pull/18/head
Simon Let 6 years ago
parent ce7768949a
commit e12e366dda
  1. 12
      Makefile
  2. 17
      cmd/collect/main.go
  3. 23
      cmd/control/cmd/debug.go
  4. 2
      cmd/control/cmd/root.go
  5. 2
      cmd/control/status/status.go
  6. 82
      cmd/daemon/main.go
  7. 48
      cmd/daemon/recall.go
  8. 47
      cmd/daemon/record.go
  9. 46
      cmd/daemon/run-server.go
  10. 38
      cmd/daemon/session-init.go
  11. 2
      cmd/postcollect/main.go
  12. 186
      cmd/session-init/main.go
  13. 44
      pkg/collect/collect.go
  14. 4
      pkg/records/records.go
  15. 7
      pkg/sess/sess.go
  16. 135
      pkg/sesshist/sesshist.go
  17. 21
      pkg/sesswatch/sesswatch.go
  18. 37
      scripts/bindutil.sh
  19. 147
      scripts/hooks.sh
  20. 43
      scripts/reshctl.sh
  21. 212
      scripts/shellrc.sh
  22. 136
      scripts/util.sh
  23. 24
      scripts/widgets.sh

@ -41,7 +41,7 @@ sanitize:
# #
# #
build: submodules bin/resh-collect bin/resh-postcollect bin/resh-daemon bin/resh-evaluate bin/resh-sanitize bin/resh-control build: submodules bin/resh-session-init bin/resh-collect bin/resh-postcollect bin/resh-daemon bin/resh-evaluate bin/resh-sanitize bin/resh-control
test_go: test_go:
# Running tests # Running tests
@ -69,7 +69,7 @@ install: build submodules/bash-preexec/bash-preexec.sh scripts/shellrc.sh conf/c
cp -f conf/config.toml ~/.config/resh.toml cp -f conf/config.toml ~/.config/resh.toml
cp -f scripts/shellrc.sh ~/.resh/shellrc cp -f scripts/shellrc.sh ~/.resh/shellrc
cp -f scripts/reshctl.sh scripts/bindutil.sh scripts/widgets.sh ~/.resh/ cp -f scripts/reshctl.sh scripts/widgets.sh scripts/hooks.sh scripts/util.sh ~/.resh/
bin/resh-control completion bash > ~/.resh/bash_completion.d/_reshctl bin/resh-control completion bash > ~/.resh/bash_completion.d/_reshctl
bin/resh-control completion zsh > ~/.resh/zsh_completion.d/_reshctl bin/resh-control completion zsh > ~/.resh/zsh_completion.d/_reshctl
@ -92,6 +92,12 @@ install: build submodules/bash-preexec/bash-preexec.sh scripts/shellrc.sh conf/c
# Restarting resh daemon ... # Restarting resh daemon ...
-[ ! -f ~/.resh/resh.pid ] || kill -SIGTERM $$(cat ~/.resh/resh.pid) -[ ! -f ~/.resh/resh.pid ] || kill -SIGTERM $$(cat ~/.resh/resh.pid)
nohup resh-daemon &>/dev/null & disown nohup resh-daemon &>/dev/null & disown
# Reloading rc files
. ~/.resh/shellrc
# Generating resh-uuid
[ -e "$(HOME)/.resh/resh-uuid" ] \
|| cat /proc/sys/kernel/random/uuid > "$(HOME)/.resh/resh-uuid" 2>/dev/null \
|| ./uuid.sh > "$(HOME)/.resh/resh-uuid" 2>/dev/null
# Final touch # Final touch
touch ~/.resh_history.json touch ~/.resh_history.json
# #
@ -127,7 +133,7 @@ uninstall:
bin/resh-control: cmd/control/cmd/*.go bin/resh-control: cmd/control/cmd/*.go
bin/resh-%: cmd/%/main.go pkg/*/*.go VERSION bin/resh-%: cmd/%/*.go pkg/*/*.go VERSION
go build ${GOFLAGS} -o $@ cmd/$*/*.go go build ${GOFLAGS} -o $@ cmd/$*/*.go
$(HOME)/.resh $(HOME)/.resh/bin $(HOME)/.config $(HOME)/.resh/bash_completion.d $(HOME)/.resh/zsh_completion.d: $(HOME)/.resh $(HOME)/.resh/bin $(HOME)/.config $(HOME)/.resh/bash_completion.d $(HOME)/.resh/zsh_completion.d:

@ -35,6 +35,9 @@ func main() {
if _, err := toml.DecodeFile(configPath, &config); err != nil { if _, err := toml.DecodeFile(configPath, &config); err != nil {
log.Fatal("Error reading config:", err) log.Fatal("Error reading config:", err)
} }
recall := flag.Bool("recall", false, "Recall command on position --histno")
recallHistno := flag.Int("histno", 0, "Recall command on position --histno")
showVersion := flag.Bool("version", false, "Show version and exit") showVersion := flag.Bool("version", false, "Show version and exit")
showRevision := flag.Bool("revision", false, "Show git revision and exit") showRevision := flag.Bool("revision", false, "Show git revision and exit")
@ -114,6 +117,10 @@ func main() {
")") ")")
os.Exit(3) os.Exit(3)
} }
if *recallHistno != 0 && *recall == false {
log.Println("Option '--recall' only works with '--histno' option - exiting!")
os.Exit(4)
}
realtimeBefore, err := strconv.ParseFloat(*rtb, 64) realtimeBefore, err := strconv.ParseFloat(*rtb, 64)
if err != nil { if err != nil {
log.Fatal("Flag Parsing error (rtb):", err) log.Fatal("Flag Parsing error (rtb):", err)
@ -159,6 +166,8 @@ func main() {
Lines: *lines, Lines: *lines,
// core // core
BaseRecord: records.BaseRecord{ BaseRecord: records.BaseRecord{
RecallHistno: *recallHistno,
CmdLine: *cmdLine, CmdLine: *cmdLine,
ExitCode: *exitCode, ExitCode: *exitCode,
Shell: *shell, Shell: *shell,
@ -178,7 +187,7 @@ func main() {
// non-posix // non-posix
RealPwd: realPwd, RealPwd: realPwd,
Pid: *pid, Pid: *pid,
SessionPid: *sessionPid, SessionPID: *sessionPid,
Host: *host, Host: *host,
Hosttype: *hosttype, Hosttype: *hosttype,
Ostype: *ostype, Ostype: *ostype,
@ -212,5 +221,9 @@ func main() {
ReshRevision: Revision, ReshRevision: Revision,
}, },
} }
collect.SendRecord(rec, strconv.Itoa(config.Port)) if *recall {
fmt.Print(collect.SendRecallRequest(rec, strconv.Itoa(config.Port)))
} else {
collect.SendRecord(rec, strconv.Itoa(config.Port), "/record")
}
} }

@ -10,16 +10,33 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// completionCmd represents the completion command
var debugCmd = &cobra.Command{ var debugCmd = &cobra.Command{
Use: "debug", Use: "debug",
Short: "Shows logs and output from last runs of resh", Short: "Debug utils for resh",
Long: "Shows logs and output from last runs of resh", Long: "Reloads resh rc files. Shows logs and output from last runs of resh",
}
var debugReloadCmd = &cobra.Command{
Use: "reload",
Short: "Reload resh rc files",
Long: "Reload resh rc files",
Run: func(cmd *cobra.Command, args []string) {
exitCode = status.ReloadRcFiles
},
}
var debugOutputCmd = &cobra.Command{
Use: "output",
Short: "Shows output from last runs of resh",
Long: "Shows output from last runs of resh",
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
files := []string{ files := []string{
"daemon_last_run_out.txt", "daemon_last_run_out.txt",
"collect_last_run_out.txt", "collect_last_run_out.txt",
"postcollect_last_run_out.txt", "postcollect_last_run_out.txt",
"session_init_last_run_out.txt",
"arrow_up_last_run_out.txt",
"arrow_down_last_run_out.txt",
} }
usr, _ := user.Current() usr, _ := user.Current()
dir := usr.HomeDir dir := usr.HomeDir

@ -28,6 +28,8 @@ func Execute() status.Code {
completionCmd.AddCommand(completionZshCmd) completionCmd.AddCommand(completionZshCmd)
rootCmd.AddCommand(debugCmd) rootCmd.AddCommand(debugCmd)
debugCmd.AddCommand(debugReloadCmd)
debugCmd.AddCommand(debugOutputCmd)
if err := rootCmd.Execute(); err != nil { if err := rootCmd.Execute(); err != nil {
fmt.Println(err) fmt.Println(err)
return status.Fail return status.Fail

@ -12,4 +12,6 @@ const (
EnableAll = 100 EnableAll = 100
// DisableAll exit code - tells reshctl() wrapper to disable_all // DisableAll exit code - tells reshctl() wrapper to disable_all
DisableAll = 110 DisableAll = 110
// ReloadRcFiles exit code - tells reshctl() wrapper to reload shellrc resh file
ReloadRcFiles = 200
) )

@ -1,7 +1,7 @@
package main package main
import ( import (
"encoding/json"
//"flag" //"flag"
"io/ioutil" "io/ioutil"
"log" "log"
@ -15,9 +15,6 @@ import (
"github.com/BurntSushi/toml" "github.com/BurntSushi/toml"
"github.com/curusarn/resh/pkg/cfg" "github.com/curusarn/resh/pkg/cfg"
"github.com/curusarn/resh/pkg/histfile"
"github.com/curusarn/resh/pkg/records"
"github.com/curusarn/resh/pkg/sesswatch"
) )
// Version from git set during build // Version from git set during build
@ -85,62 +82,6 @@ func statusHandler(w http.ResponseWriter, r *http.Request) {
log.Println("Status OK") log.Println("Status OK")
} }
type recordHandler struct {
subscribers []chan records.Record
}
func (h *recordHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK\n"))
jsn, err := ioutil.ReadAll(r.Body)
// run rest of the handler as goroutine to prevent any hangups
go func() {
if err != nil {
log.Println("Error reading the body", err)
return
}
record := records.Record{}
err = json.Unmarshal(jsn, &record)
if err != nil {
log.Println("Decoding error: ", err)
log.Println("Payload: ", jsn)
return
}
for _, sub := range h.subscribers {
sub <- record
}
part := "2"
if record.PartOne {
part = "1"
}
log.Println("Received:", record.CmdLine, " - part", part)
}()
// fmt.Println("cmd:", r.CmdLine)
// fmt.Println("pwd:", r.Pwd)
// fmt.Println("git:", r.GitWorkTree)
// fmt.Println("exit_code:", r.ExitCode)
}
func runServer(config cfg.Config, outputPath string) {
var recordSubscribers []chan records.Record
histfileChan := make(chan records.Record)
recordSubscribers = append(recordSubscribers, histfileChan)
sessionsToDrop := make(chan string)
histfile.Go(histfileChan, outputPath, sessionsToDrop)
sesswatchChan := make(chan records.Record)
recordSubscribers = append(recordSubscribers, sesswatchChan)
sesswatch.Go(sesswatchChan, []chan string{sessionsToDrop}, config.SesswatchPeriodSeconds)
http.HandleFunc("/status", statusHandler)
http.Handle("/record", &recordHandler{subscribers: recordSubscribers})
//http.Handle("/session_init", &sessionInitHandler{OutputPath: outputPath})
//http.Handle("/recall", &recallHandler{OutputPath: outputPath})
http.ListenAndServe(":"+strconv.Itoa(config.Port), nil)
}
func killDaemon(pidfile string) error { func killDaemon(pidfile string) error {
dat, err := ioutil.ReadFile(pidfile) dat, err := ioutil.ReadFile(pidfile)
if err != nil { if err != nil {
@ -170,25 +111,4 @@ func isDaemonRunning(port int) (bool, error) {
} }
defer resp.Body.Close() defer resp.Body.Close()
return true, nil return true, nil
//body, err := ioutil.ReadAll(resp.Body)
// dat, err := ioutil.ReadFile(pidfile)
// if err != nil {
// log.Println("Reading pid file failed", err)
// return false, err
// }
// log.Print(string(dat))
// pid, err := strconv.ParseInt(string(dat), 10, 64)
// if err != nil {
// log.Fatal(err)
// }
// process, err := os.FindProcess(int(pid))
// if err != nil {
// log.Printf("Failed to find process: %s\n", err)
// return false, err
// } else {
// err := process.Signal(syscall.Signal(0))
// log.Printf("process.Signal on pid %d returned: %v\n", pid, err)
// }
// return true, nil
} }

@ -0,0 +1,48 @@
package main
import (
"encoding/json"
"io/ioutil"
"log"
"net/http"
"github.com/curusarn/resh/pkg/collect"
"github.com/curusarn/resh/pkg/records"
"github.com/curusarn/resh/pkg/sesshist"
)
type recallHandler struct {
sesshistDispatch *sesshist.Dispatch
}
func (h *recallHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
jsn, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Println("Error reading the body", err)
return
}
rec := records.Record{}
err = json.Unmarshal(jsn, &rec)
if err != nil {
log.Println("Decoding error:", err)
log.Println("Payload:", jsn)
return
}
cmd, err := h.sesshistDispatch.Recall(rec.SessionID, rec.RecallHistno)
if err != nil {
log.Println("/recall - sess id:", rec.SessionID, " - histno:", rec.RecallHistno, " -> ERROR")
log.Println("Recall error:", err)
return
}
resp := collect.SingleResponse{cmd}
jsn, err = json.Marshal(&resp)
if err != nil {
log.Println("Encoding error:", err)
log.Println("Response:", resp)
return
}
log.Println(string(jsn))
w.Write(jsn)
log.Println("/recall - sess id:", rec.SessionID, " - histno:", rec.RecallHistno, " -> ", cmd)
}

@ -0,0 +1,47 @@
package main
import (
"encoding/json"
"io/ioutil"
"log"
"net/http"
"github.com/curusarn/resh/pkg/records"
)
type recordHandler struct {
subscribers []chan records.Record
}
func (h *recordHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK\n"))
jsn, err := ioutil.ReadAll(r.Body)
// run rest of the handler as goroutine to prevent any hangups
go func() {
if err != nil {
log.Println("Error reading the body", err)
return
}
record := records.Record{}
err = json.Unmarshal(jsn, &record)
if err != nil {
log.Println("Decoding error: ", err)
log.Println("Payload: ", jsn)
return
}
for _, sub := range h.subscribers {
sub <- record
}
part := "2"
if record.PartOne {
part = "1"
}
log.Println("/record - ", record.CmdLine, " - part", part)
}()
// fmt.Println("cmd:", r.CmdLine)
// fmt.Println("pwd:", r.Pwd)
// fmt.Println("git:", r.GitWorkTree)
// fmt.Println("exit_code:", r.ExitCode)
}

@ -0,0 +1,46 @@
package main
import (
"net/http"
"strconv"
"github.com/curusarn/resh/pkg/cfg"
"github.com/curusarn/resh/pkg/histfile"
"github.com/curusarn/resh/pkg/records"
"github.com/curusarn/resh/pkg/sesshist"
"github.com/curusarn/resh/pkg/sesswatch"
)
func runServer(config cfg.Config, outputPath string) {
var recordSubscribers []chan records.Record
var sessionInitSubscribers []chan records.Record
var sessionDropSubscribers []chan string
// sessshist
sesshistSessionsToInit := make(chan records.Record)
sessionInitSubscribers = append(sessionInitSubscribers, sesshistSessionsToInit)
sesshistSessionsToDrop := make(chan string)
sessionDropSubscribers = append(sessionDropSubscribers, sesshistSessionsToDrop)
sesshistRecords := make(chan records.Record)
recordSubscribers = append(recordSubscribers, sesshistRecords)
sesshistDispatch := sesshist.NewDispatch(sesshistSessionsToInit, sesshistSessionsToDrop, sesshistRecords)
// histfile
histfileRecords := make(chan records.Record)
recordSubscribers = append(recordSubscribers, histfileRecords)
histfileSessionsToDrop := make(chan string)
sessionDropSubscribers = append(sessionDropSubscribers, histfileSessionsToDrop)
histfile.Go(histfileRecords, outputPath, histfileSessionsToDrop)
// sesswatch
sesswatchSessionsToWatch := make(chan records.Record)
sessionInitSubscribers = append(sessionInitSubscribers, sesswatchSessionsToWatch)
sesswatch.Go(sesswatchSessionsToWatch, sessionDropSubscribers, config.SesswatchPeriodSeconds)
// handlers
http.HandleFunc("/status", statusHandler)
http.Handle("/record", &recordHandler{subscribers: recordSubscribers})
http.Handle("/session_init", &sessionInitHandler{subscribers: sessionInitSubscribers})
http.Handle("/recall", &recallHandler{sesshistDispatch: sesshistDispatch})
http.ListenAndServe(":"+strconv.Itoa(config.Port), nil)
}

@ -0,0 +1,38 @@
package main
import (
"encoding/json"
"io/ioutil"
"log"
"net/http"
"github.com/curusarn/resh/pkg/records"
)
type sessionInitHandler struct {
subscribers []chan records.Record
}
func (h *sessionInitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("OK\n"))
jsn, err := ioutil.ReadAll(r.Body)
// run rest of the handler as goroutine to prevent any hangups
go func() {
if err != nil {
log.Println("Error reading the body", err)
return
}
record := records.Record{}
err = json.Unmarshal(jsn, &record)
if err != nil {
log.Println("Decoding error: ", err)
log.Println("Payload: ", jsn)
return
}
for _, sub := range h.subscribers {
sub <- record
}
log.Println("/session_init - id:", record.SessionID, " - pid:", record.SessionPID)
}()
}

@ -143,5 +143,5 @@ func main() {
ReshRevision: Revision, ReshRevision: Revision,
}, },
} }
collect.SendRecord(rec, strconv.Itoa(config.Port)) collect.SendRecord(rec, strconv.Itoa(config.Port), "/record")
} }

@ -0,0 +1,186 @@
package main
import (
"flag"
"fmt"
"log"
"os"
"github.com/BurntSushi/toml"
"github.com/curusarn/resh/pkg/cfg"
"github.com/curusarn/resh/pkg/collect"
"github.com/curusarn/resh/pkg/records"
"os/user"
"path/filepath"
"strconv"
)
// Version from git set during build
var Version string
// Revision from git set during build
var Revision string
func main() {
usr, _ := user.Current()
dir := usr.HomeDir
configPath := filepath.Join(dir, "/.config/resh.toml")
reshUUIDPath := filepath.Join(dir, "/.resh/resh-uuid")
machineIDPath := "/etc/machine-id"
var config cfg.Config
if _, err := toml.DecodeFile(configPath, &config); err != nil {
log.Fatal("Error reading config:", err)
}
showVersion := flag.Bool("version", false, "Show version and exit")
showRevision := flag.Bool("revision", false, "Show git revision and exit")
requireVersion := flag.String("requireVersion", "", "abort if version doesn't match")
requireRevision := flag.String("requireRevision", "", "abort if revision doesn't match")
shell := flag.String("shell", "", "actual shell")
uname := flag.String("uname", "", "uname")
sessionID := flag.String("sessionId", "", "resh generated session id")
// posix variables
cols := flag.String("cols", "-1", "$COLUMNS")
lines := flag.String("lines", "-1", "$LINES")
home := flag.String("home", "", "$HOME")
lang := flag.String("lang", "", "$LANG")
lcAll := flag.String("lcAll", "", "$LC_ALL")
login := flag.String("login", "", "$LOGIN")
shellEnv := flag.String("shellEnv", "", "$SHELL")
term := flag.String("term", "", "$TERM")
// non-posix
pid := flag.Int("pid", -1, "$$")
sessionPid := flag.Int("sessionPid", -1, "$$ at session start")
shlvl := flag.Int("shlvl", -1, "$SHLVL")
host := flag.String("host", "", "$HOSTNAME")
hosttype := flag.String("hosttype", "", "$HOSTTYPE")
ostype := flag.String("ostype", "", "$OSTYPE")
machtype := flag.String("machtype", "", "$MACHTYPE")
// before after
timezoneBefore := flag.String("timezoneBefore", "", "")
osReleaseID := flag.String("osReleaseId", "", "/etc/os-release ID")
osReleaseVersionID := flag.String("osReleaseVersionId", "",
"/etc/os-release ID")
osReleaseIDLike := flag.String("osReleaseIdLike", "", "/etc/os-release ID")
osReleaseName := flag.String("osReleaseName", "", "/etc/os-release ID")
osReleasePrettyName := flag.String("osReleasePrettyName", "",
"/etc/os-release ID")
rtb := flag.String("realtimeBefore", "-1", "before $EPOCHREALTIME")
rtsess := flag.String("realtimeSession", "-1",
"on session start $EPOCHREALTIME")
rtsessboot := flag.String("realtimeSessSinceBoot", "-1",
"on session start $EPOCHREALTIME")
flag.Parse()
if *showVersion == true {
fmt.Println(Version)
os.Exit(0)
}
if *showRevision == true {
fmt.Println(Revision)
os.Exit(0)
}
if *requireVersion != "" && *requireVersion != Version {
fmt.Println("Please restart/reload this terminal session " +
"(resh version: " + Version +
"; resh version of this terminal session: " + *requireVersion +
")")
os.Exit(3)
}
if *requireRevision != "" && *requireRevision != Revision {
fmt.Println("Please restart/reload this terminal session " +
"(resh revision: " + Revision +
"; resh revision of this terminal session: " + *requireRevision +
")")
os.Exit(3)
}
realtimeBefore, err := strconv.ParseFloat(*rtb, 64)
if err != nil {
log.Fatal("Flag Parsing error (rtb):", err)
}
realtimeSessionStart, err := strconv.ParseFloat(*rtsess, 64)
if err != nil {
log.Fatal("Flag Parsing error (rt sess):", err)
}
realtimeSessSinceBoot, err := strconv.ParseFloat(*rtsessboot, 64)
if err != nil {
log.Fatal("Flag Parsing error (rt sess boot):", err)
}
realtimeSinceSessionStart := realtimeBefore - realtimeSessionStart
realtimeSinceBoot := realtimeSessSinceBoot + realtimeSinceSessionStart
timezoneBeforeOffset := collect.GetTimezoneOffsetInSeconds(*timezoneBefore)
realtimeBeforeLocal := realtimeBefore + timezoneBeforeOffset
if *osReleaseID == "" {
*osReleaseID = "linux"
}
if *osReleaseName == "" {
*osReleaseName = "Linux"
}
if *osReleasePrettyName == "" {
*osReleasePrettyName = "Linux"
}
rec := records.Record{
// posix
Cols: *cols,
Lines: *lines,
// core
BaseRecord: records.BaseRecord{
Shell: *shell,
Uname: *uname,
SessionID: *sessionID,
// posix
Home: *home,
Lang: *lang,
LcAll: *lcAll,
Login: *login,
// Path: *path,
ShellEnv: *shellEnv,
Term: *term,
// non-posix
Pid: *pid,
SessionPID: *sessionPid,
Host: *host,
Hosttype: *hosttype,
Ostype: *ostype,
Machtype: *machtype,
Shlvl: *shlvl,
// before after
TimezoneBefore: *timezoneBefore,
RealtimeBefore: realtimeBefore,
RealtimeBeforeLocal: realtimeBeforeLocal,
RealtimeSinceSessionStart: realtimeSinceSessionStart,
RealtimeSinceBoot: realtimeSinceBoot,
MachineID: collect.ReadFileContent(machineIDPath),
OsReleaseID: *osReleaseID,
OsReleaseVersionID: *osReleaseVersionID,
OsReleaseIDLike: *osReleaseIDLike,
OsReleaseName: *osReleaseName,
OsReleasePrettyName: *osReleasePrettyName,
ReshUUID: collect.ReadFileContent(reshUUIDPath),
ReshVersion: Version,
ReshRevision: Revision,
},
}
collect.SendRecord(rec, strconv.Itoa(config.Port), "/session_init")
}

@ -13,14 +13,54 @@ import (
"github.com/curusarn/resh/pkg/records" "github.com/curusarn/resh/pkg/records"
) )
// SingleResponse json struct
type SingleResponse struct {
CmdLine string `json:"cmdline"`
}
// SendRecallRequest to daemon
func SendRecallRequest(r records.Record, port string) string {
recJSON, err := json.Marshal(r)
if err != nil {
log.Fatal("send err 1", err)
}
req, err := http.NewRequest("POST", "http://localhost:"+port+"/recall",
bytes.NewBuffer(recJSON))
if err != nil {
log.Fatal("send err 2", err)
}
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatal("resh-daemon is not running :(")
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal("read response error")
}
log.Println(string(body))
response := SingleResponse{}
err = json.Unmarshal(body, &response)
if err != nil {
log.Fatal("unmarshal resp error: ", err)
}
log.Println(response)
return response.CmdLine
}
// SendRecord to daemon // SendRecord to daemon
func SendRecord(r records.Record, port string) { func SendRecord(r records.Record, port, path string) {
recJSON, err := json.Marshal(r) recJSON, err := json.Marshal(r)
if err != nil { if err != nil {
log.Fatal("send err 1", err) log.Fatal("send err 1", err)
} }
req, err := http.NewRequest("POST", "http://localhost:"+port+"/record", req, err := http.NewRequest("POST", "http://localhost:"+port+path,
bytes.NewBuffer(recJSON)) bytes.NewBuffer(recJSON))
if err != nil { if err != nil {
log.Fatal("send err 2", err) log.Fatal("send err 2", err)

@ -35,7 +35,7 @@ type BaseRecord struct {
RealPwd string `json:"realPwd"` RealPwd string `json:"realPwd"`
RealPwdAfter string `json:"realPwdAfter"` RealPwdAfter string `json:"realPwdAfter"`
Pid int `json:"pid"` Pid int `json:"pid"`
SessionPid int `json:"sessionPid"` SessionPID int `json:"sessionPid"`
Host string `json:"host"` Host string `json:"host"`
Hosttype string `json:"hosttype"` Hosttype string `json:"hosttype"`
Ostype string `json:"ostype"` Ostype string `json:"ostype"`
@ -82,7 +82,7 @@ type BaseRecord struct {
// recall metadata // recall metadata
Recalled bool `json:"recalled"` Recalled bool `json:"recalled"`
RecallHistno string `json:"recallHistno,omitempty"` RecallHistno int `json:"recallHistno,omitempty"`
RecallStrategy string `json:"recallStrategy,omitempty"` RecallStrategy string `json:"recallStrategy,omitempty"`
RecallActions []string `json:"recallActions,omitempty"` RecallActions []string `json:"recallActions,omitempty"`

@ -0,0 +1,7 @@
package sess
// Session represents a session, used for sennding through channels when more than just ID is needed
type Session struct {
ID string
PID int
}

@ -0,0 +1,135 @@
package sesshist
import (
"errors"
"log"
"strconv"
"sync"
"github.com/curusarn/resh/pkg/records"
)
// Dispatch Recall() calls to an apropriate session history (sesshist)
type Dispatch struct {
sessions map[string]*sesshist
mutex sync.RWMutex
}
// NewDispatch creates a new sesshist.Dispatch and starts necessary gorutines
func NewDispatch(sessionsToInit chan records.Record, sessionsToDrop chan string, recordsToAdd chan records.Record) *Dispatch {
s := Dispatch{sessions: map[string]*sesshist{}}
go s.sessionInitializer(sessionsToInit)
go s.sessionDropper(sessionsToDrop)
go s.recordAdder(recordsToAdd)
return &s
}
func (s *Dispatch) sessionInitializer(sessionsToInit chan records.Record) {
for {
record := <-sessionsToInit
log.Println("sesshist: got session to init - " + record.SessionID)
s.initSession(record.SessionID)
}
}
func (s *Dispatch) sessionDropper(sessionsToDrop chan string) {
for {
sessionID := <-sessionsToDrop
log.Println("sesshist: got session to drop - " + sessionID)
s.dropSession(sessionID)
}
}
func (s *Dispatch) recordAdder(recordsToAdd chan records.Record) {
for {
record := <-recordsToAdd
if record.PartOne {
log.Println("sesshist: got record to add - " + record.CmdLine)
s.addRecentRecord(record.SessionID, record)
}
// TODO: we will need to handle part2 as well eventually
}
}
// InitSession struct
func (s *Dispatch) initSession(sessionID string) error {
s.mutex.RLock()
_, found := s.sessions[sessionID]
s.mutex.RUnlock()
if found == true {
return errors.New("sesshist ERROR: Can't INIT already existing session " + sessionID)
}
s.mutex.Lock()
defer s.mutex.Unlock()
s.sessions[sessionID] = &sesshist{}
return nil
}
// DropSession struct
func (s *Dispatch) dropSession(sessionID string) error {
s.mutex.RLock()
_, found := s.sessions[sessionID]
s.mutex.RUnlock()
if found == false {
return errors.New("sesshist ERROR: Can't DROP not existing session " + sessionID)
}
s.mutex.Lock()
defer s.mutex.Unlock()
delete(s.sessions, sessionID)
return nil
}
// AddRecent record to session
func (s *Dispatch) addRecentRecord(sessionID string, record records.Record) error {
s.mutex.RLock()
session, found := s.sessions[sessionID]
s.mutex.RUnlock()
if found == false {
return errors.New("sesshist ERROR: No session history for SessionID " + sessionID + " (should we create one?)")
}
session.mutex.Lock()
defer session.mutex.Unlock()
session.recent = append(session.recent, record)
log.Println("sesshist: record:", record.CmdLine, "; added to session:", sessionID, "; session len:", len(session.recent))
return nil
}
// Recall command from recent session history
func (s *Dispatch) Recall(sessionID string, histno int) (string, error) {
s.mutex.RLock()
session, found := s.sessions[sessionID]
s.mutex.RUnlock()
if found == false {
return "", errors.New("sesshist ERROR: No session history for SessionID " + sessionID)
}
session.mutex.Lock()
defer session.mutex.Unlock()
return session.getRecordByHistno(histno)
}
type sesshist struct {
recent []records.Record
mutex sync.Mutex
}
func (s *sesshist) getRecordByHistno(histno int) (string, error) {
// records get appended to the end of the slice
// -> this func handles the indexing
if histno == 0 {
return "", errors.New("sesshist ERROR: 'histno == 0' is not a record from history")
}
if histno < 0 {
return "", errors.New("sesshist ERROR: 'histno < 0' is a command from future (not supperted yet)")
}
index := len(s.recent) - histno
if index < 0 {
return "", errors.New("sesshist ERROR: 'histno > number of commands in the session' (" + strconv.Itoa(len(s.recent)) + ")")
}
return s.recent[index].CmdLine, nil
}

@ -18,28 +18,23 @@ type sesswatch struct {
} }
// Go runs the session watcher - watches sessions and sends // Go runs the session watcher - watches sessions and sends
func Go(input chan records.Record, sessionsToDrop []chan string, sleepSeconds uint) { func Go(sessionsToWatch chan records.Record, sessionsToDrop []chan string, sleepSeconds uint) {
sw := sesswatch{sessionsToDrop: sessionsToDrop, sleepSeconds: sleepSeconds, watchedSessions: map[string]bool{}} sw := sesswatch{sessionsToDrop: sessionsToDrop, sleepSeconds: sleepSeconds, watchedSessions: map[string]bool{}}
go sw.waiter(input) go sw.waiter(sessionsToWatch)
} }
func (s *sesswatch) waiter(sessionsToWatch chan records.Record) { func (s *sesswatch) waiter(sessionsToWatch chan records.Record) {
for { for {
func() { func() {
record := <-sessionsToWatch record := <-sessionsToWatch
session := record.SessionID id := record.SessionID
pid := record.SessionPid pid := record.SessionPID
if record.PartOne == false {
log.Println("sesswatch: part2 - ignoring:", session, "~", pid)
return // continue
}
log.Println("sesswatch: got session ~ pid:", session, "~", pid)
s.mutex.Lock() s.mutex.Lock()
defer s.mutex.Unlock() defer s.mutex.Unlock()
if s.watchedSessions[session] == false { if s.watchedSessions[id] == false {
log.Println("sesswatch: start watching NEW session ~ pid:", session, "~", pid) log.Println("sesswatch: start watching NEW session ~ pid:", id, "~", pid)
s.watchedSessions[session] = true s.watchedSessions[id] = true
go s.watcher(session, record.SessionPid) go s.watcher(id, pid)
} }
}() }()
} }

@ -1,37 +0,0 @@
# shellcheck source=../submodules/bash-zsh-compat-widgets/bindfunc.sh
. ~/.resh/bindfunc.sh
# shellcheck source=widgets.sh
. ~/.resh/widgets.sh
__resh_bind_arrows() {
echo "bindfunc __resh_widget_arrow_up"
echo "bindfunc __resh_widget_arrow_down"
return 0
}
__resh_bind_control_R() {
echo "bindfunc __resh_widget_control_R"
return 0
}
__resh_unbind_arrows() {
echo "\ bindfunc __resh_widget_arrow_up"
echo "\ bindfunc __resh_widget_arrow_down"
return 0
}
__resh_unbind_control_R() {
echo "\ bindfunc __resh_widget_control_R"
return 0
}
__resh_bind_all() {
__resh_bind_arrows
__resh_bind_control_R
}
__resh_unbind_all() {
__resh_unbind_arrows
__resh_unbind_control_R
}

@ -0,0 +1,147 @@
__resh_preexec() {
__RESH_HISTNO=0
# core
__RESH_COLLECT=1
__RESH_CMDLINE="$1" # not local to preserve it for postcollect (useful as sanity check)
__resh_collect --cmdLine "$__RESH_CMDLINE" \
&>~/.resh/collect_last_run_out.txt || echo "resh-collect ERROR: $(head -n 1 ~/.resh/collect_last_run_out.txt)"
}
# used for collect and collect --recall
__resh_collect() {
# posix
local __RESH_COLS="$COLUMNS"
local __RESH_LANG="$LANG"
local __RESH_LC_ALL="$LC_ALL"
# other LC ?
local __RESH_LINES="$LINES"
# __RESH_PATH="$PATH"
local __RESH_PWD="$PWD"
# non-posix
local __RESH_SHLVL="$SHLVL"
local __RESH_GIT_CDUP; __RESH_GIT_CDUP="$(git rev-parse --show-cdup 2>/dev/null)"
local __RESH_GIT_CDUP_EXIT_CODE=$?
local __RESH_GIT_REMOTE; __RESH_GIT_REMOTE="$(git remote get-url origin 2>/dev/null)"
local __RESH_GIT_REMOTE_EXIT_CODE=$?
#__RESH_GIT_TOPLEVEL="$(git rev-parse --show-toplevel)"
#__RESH_GIT_TOPLEVEL_EXIT_CODE=$?
if [ -n "$ZSH_VERSION" ]; then
# assume Zsh
local __RESH_PID="$$" # current pid
elif [ -n "$BASH_VERSION" ]; then
# assume Bash
local __RESH_PID="$BASHPID" # current pid
fi
# time
local __RESH_TZ_BEFORE; __RESH_TZ_BEFORE=$(date +%z)
# __RESH_RT_BEFORE="$EPOCHREALTIME"
__RESH_RT_BEFORE=$(__resh_get_epochrealtime)
if [ "$__RESH_VERSION" != "$(resh-collect -version)" ]; then
# shellcheck source=shellrc.sh
source ~/.resh/shellrc
if [ "$__RESH_VERSION" != "$(resh-collect -version)" ]; then
echo "RESH WARNING: You probably just updated RESH - PLEASE RESTART OR RELOAD THIS TERMINAL SESSION (resh version: $(resh-collect -version); resh version of this terminal session: ${__RESH_VERSION})"
else
echo "RESH INFO: New RESH shellrc script was loaded - if you encounter any issues please restart this terminal session."
fi
elif [ "$__RESH_REVISION" != "$(resh-collect -revision)" ]; then
# shellcheck source=shellrc.sh
source ~/.resh/shellrc
if [ "$__RESH_REVISION" != "$(resh-collect -revision)" ]; then
echo "RESH WARNING: You probably just updated RESH - PLEASE RESTART OR RELOAD THIS TERMINAL SESSION (resh revision: $(resh-collect -revision); resh revision of this terminal session: ${__RESH_REVISION})"
fi
fi
if [ "$__RESH_VERSION" = "$(resh-collect -version)" ] && [ "$__RESH_REVISION" = "$(resh-collect -revision)" ]; then
resh-collect -requireVersion "$__RESH_VERSION" \
-requireRevision "$__RESH_REVISION" \
-shell "$__RESH_SHELL" \
-uname "$__RESH_UNAME" \
-sessionId "$__RESH_SESSION_ID" \
-cols "$__RESH_COLS" \
-home "$__RESH_HOME" \
-lang "$__RESH_LANG" \
-lcAll "$__RESH_LC_ALL" \
-lines "$__RESH_LINES" \
-login "$__RESH_LOGIN" \
-pwd "$__RESH_PWD" \
-shellEnv "$__RESH_SHELL_ENV" \
-term "$__RESH_TERM" \
-pid "$__RESH_PID" \
-sessionPid "$__RESH_SESSION_PID" \
-host "$__RESH_HOST" \
-hosttype "$__RESH_HOSTTYPE" \
-ostype "$__RESH_OSTYPE" \
-machtype "$__RESH_MACHTYPE" \
-shlvl "$__RESH_SHLVL" \
-gitCdup "$__RESH_GIT_CDUP" \
-gitCdupExitCode "$__RESH_GIT_CDUP_EXIT_CODE" \
-gitRemote "$__RESH_GIT_REMOTE" \
-gitRemoteExitCode "$__RESH_GIT_REMOTE_EXIT_CODE" \
-realtimeBefore "$__RESH_RT_BEFORE" \
-realtimeSession "$__RESH_RT_SESSION" \
-realtimeSessSinceBoot "$__RESH_RT_SESS_SINCE_BOOT" \
-timezoneBefore "$__RESH_TZ_BEFORE" \
-osReleaseId "$__RESH_OS_RELEASE_ID" \
-osReleaseVersionId "$__RESH_OS_RELEASE_VERSION_ID" \
-osReleaseIdLike "$__RESH_OS_RELEASE_ID_LIKE" \
-osReleaseName "$__RESH_OS_RELEASE_NAME" \
-osReleasePrettyName "$__RESH_OS_RELEASE_PRETTY_NAME" \
"$@"
fi
}
__resh_precmd() {
local __RESH_EXIT_CODE=$?
local __RESH_RT_AFTER
local __RESH_TZ_AFTER
local __RESH_PWD_AFTER
local __RESH_GIT_CDUP_AFTER
local __RESH_GIT_CDUP_EXIT_CODE_AFTER
local __RESH_GIT_REMOTE_AFTER
local __RESH_GIT_REMOTE_EXIT_CODE_AFTER
__RESH_RT_AFTER=$(__resh_get_epochrealtime)
__RESH_TZ_AFTER=$(date +%z)
__RESH_PWD_AFTER="$PWD"
__RESH_GIT_CDUP_AFTER="$(git rev-parse --show-cdup 2>/dev/null)"
__RESH_GIT_CDUP_EXIT_CODE_AFTER=$?
__RESH_GIT_REMOTE_AFTER="$(git remote get-url origin 2>/dev/null)"
__RESH_GIT_REMOTE_EXIT_CODE_AFTER=$?
if [ -n "${__RESH_COLLECT}" ]; then
if [ "$__RESH_VERSION" != "$(resh-postcollect -version)" ]; then
# shellcheck source=shellrc.sh
source ~/.resh/shellrc
if [ "$__RESH_VERSION" != "$(resh-postcollect -version)" ]; then
echo "RESH WARNING: You probably just updated RESH - PLEASE RESTART OR RELOAD THIS TERMINAL SESSION (resh version: $(resh-collect -version); resh version of this terminal session: ${__RESH_VERSION})"
else
echo "RESH INFO: New RESH shellrc script was loaded - if you encounter any issues please restart this terminal session."
fi
elif [ "$__RESH_REVISION" != "$(resh-postcollect -revision)" ]; then
# shellcheck source=shellrc.sh
source ~/.resh/shellrc
if [ "$__RESH_REVISION" != "$(resh-postcollect -revision)" ]; then
echo "RESH WARNING: You probably just updated RESH - PLEASE RESTART OR RELOAD THIS TERMINAL SESSION (resh revision: $(resh-collect -revision); resh revision of this terminal session: ${__RESH_REVISION})"
fi
fi
if [ "$__RESH_VERSION" = "$(resh-postcollect -version)" ] && [ "$__RESH_REVISION" = "$(resh-postcollect -revision)" ]; then
resh-postcollect -requireVersion "$__RESH_VERSION" \
-requireRevision "$__RESH_REVISION" \
-cmdLine "$__RESH_CMDLINE" \
-realtimeBefore "$__RESH_RT_BEFORE" \
-exitCode "$__RESH_EXIT_CODE" \
-sessionId "$__RESH_SESSION_ID" \
-pwdAfter "$__RESH_PWD_AFTER" \
-gitCdupAfter "$__RESH_GIT_CDUP_AFTER" \
-gitCdupExitCodeAfter "$__RESH_GIT_CDUP_EXIT_CODE_AFTER" \
-gitRemoteAfter "$__RESH_GIT_REMOTE_AFTER" \
-gitRemoteExitCodeAfter "$__RESH_GIT_REMOTE_EXIT_CODE_AFTER" \
-realtimeAfter "$__RESH_RT_AFTER" \
-timezoneAfter "$__RESH_TZ_AFTER" \
&>~/.resh/postcollect_last_run_out.txt || echo "resh-postcollect ERROR: $(head -n 1 ~/.resh/postcollect_last_run_out.txt)"
fi
fi
unset __RESH_COLLECT
}

@ -1,7 +1,39 @@
# source bindutil - contains functions to bind and unbind RESH widgets # shellcheck source=../submodules/bash-zsh-compat-widgets/bindfunc.sh
# shellcheck source=bindutil.sh . ~/.resh/bindfunc.sh
. ~/.resh/bindutil.sh # shellcheck source=widgets.sh
. ~/.resh/widgets.sh
__resh_bind_arrows() {
bindfunc '\C-k' __resh_widget_arrow_up_compat
bindfunc '\C-j' __resh_widget_arrow_down_compat
return 0
}
__resh_bind_control_R() {
echo "bindfunc __resh_widget_control_R_compat"
return 0
}
__resh_unbind_arrows() {
echo "\ bindfunc __resh_widget_arrow_up_compat"
echo "\ bindfunc __resh_widget_arrow_down_compat"
return 0
}
__resh_unbind_control_R() {
echo "\ bindfunc __resh_widget_control_R_compat"
return 0
}
__resh_bind_all() {
__resh_bind_arrows
__resh_bind_control_R
}
__resh_unbind_all() {
__resh_unbind_arrows
__resh_unbind_control_R
}
reshctl() { reshctl() {
# run resh-control aka the real reshctl # run resh-control aka the real reshctl
@ -25,6 +57,11 @@ reshctl() {
__resh_unbind_all __resh_unbind_all
return 0 return 0
;; ;;
200)
# reload rc files
. ~/.resh/shellrc
return 0
;;
*) *)
echo "reshctl() FATAL ERROR: unknown status" >&2 echo "reshctl() FATAL ERROR: unknown status" >&2
return "$status" return "$status"

@ -4,70 +4,13 @@ PATH=$PATH:~/.resh/bin
# zmodload zsh/datetime # zmodload zsh/datetime
# fi # fi
# shellcheck source=hooks.sh
. ~/.resh/hooks.sh
# shellcheck source=util.sh
. ~/.resh/util.sh
# shellcheck source=reshctl.sh # shellcheck source=reshctl.sh
. ~/.resh/reshctl.sh . ~/.resh/reshctl.sh
__resh_get_uuid() {
cat /proc/sys/kernel/random/uuid 2>/dev/null || resh-uuid
}
__resh_get_epochrealtime() {
if date +%s.%N | grep -vq 'N'; then
# GNU date
date +%s.%N
elif gdate --version >/dev/null && gdate +%s.%N | grep -vq 'N'; then
# GNU date take 2
gdate +%s.%N
elif [ -n "$ZSH_VERSION" ]; then
# zsh fallback using $EPOCHREALTIME
if [ -z "${__RESH_ZSH_LOADED_DATETIME+x}" ]; then
zmodload zsh/datetime
__RESH_ZSH_LOADED_DATETIME=1
fi
echo "$EPOCHREALTIME"
else
# dumb date
# XXX: we lost precison beyond seconds
date +%s
if [ -z "${__RESH_DATE_WARN+x}" ]; then
echo "resh WARN: can't get precise time - consider installing GNU date!"
__RESH_DATE_WARN=1
fi
fi
}
__resh_run_daemon() {
if [ -n "$ZSH_VERSION" ]; then
setopt LOCAL_OPTIONS NO_NOTIFY NO_MONITOR
fi
nohup resh-daemon &>~/.resh/daemon_last_run_out.txt & disown
}
# __resh_session_init() {
# resh-event session_start --sessionId "$__RESH_SESSION_ID" --sessionPid "$__RESH_SESSION_PID"
# }
#
__resh_bash_completion_init() {
local bash_completion_dir=~/.resh/bash_completion.d
# source user completion directory definitions
# taken from /usr/share/bash-completion/bash_completion
if [[ -d $bash_completion_dir && -r $bash_completion_dir && \
-x $bash_completion_dir ]]; then
for i in $(LC_ALL=C command ls "$bash_completion_dir"); do
i=$bash_completion_dir/$i
# shellcheck disable=SC2154
# shellcheck source=/dev/null
[[ ${i##*/} != @($_backup_glob|Makefile*|$_blacklist_glob) \
&& -f $i && -r $i ]] && . "$i"
done
fi
}
__resh_zsh_completion_init() {
# shellcheck disable=SC2206
fpath=(~/.resh/zsh_completion.d $fpath)
}
__RESH_MACOS=0 __RESH_MACOS=0
__RESH_LINUX=0 __RESH_LINUX=0
__RESH_UNAME=$(uname) __RESH_UNAME=$(uname)
@ -95,13 +38,6 @@ else
echo "resh PANIC unrecognized shell" echo "resh PANIC unrecognized shell"
fi fi
if [ -z "${__RESH_SESSION_ID+x}" ]; then
export __RESH_SESSION_ID; __RESH_SESSION_ID=$(__resh_get_uuid)
export __RESH_SESSION_PID="$$"
# TODO add sesson time
# __resh_session_init __RESH_SESSION_ID __RESH_SESSION_PID
fi
# posix # posix
__RESH_HOME="$HOME" __RESH_HOME="$HOME"
__RESH_LOGIN="$LOGNAME" __RESH_LOGIN="$LOGNAME"
@ -133,140 +69,12 @@ __RESH_REVISION=$(resh-collect -revision)
__resh_run_daemon __resh_run_daemon
__resh_preexec() { if [ -z "${__RESH_SESSION_ID+x}" ]; then
# core export __RESH_SESSION_ID; __RESH_SESSION_ID=$(__resh_get_uuid)
__RESH_COLLECT=1 export __RESH_SESSION_PID="$$"
__RESH_CMDLINE="$1" # TODO add sesson time
__resh_session_init
# posix fi
__RESH_COLS="$COLUMNS"
__RESH_LANG="$LANG"
__RESH_LC_ALL="$LC_ALL"
# other LC ?
__RESH_LINES="$LINES"
# __RESH_PATH="$PATH"
__RESH_PWD="$PWD"
# non-posix
__RESH_SHLVL="$SHLVL"
__RESH_GIT_CDUP="$(git rev-parse --show-cdup 2>/dev/null)"
__RESH_GIT_CDUP_EXIT_CODE=$?
__RESH_GIT_REMOTE="$(git remote get-url origin 2>/dev/null)"
__RESH_GIT_REMOTE_EXIT_CODE=$?
#__RESH_GIT_TOPLEVEL="$(git rev-parse --show-toplevel)"
#__RESH_GIT_TOPLEVEL_EXIT_CODE=$?
if [ -n "$ZSH_VERSION" ]; then
# assume Zsh
__RESH_PID="$$" # current pid
elif [ -n "$BASH_VERSION" ]; then
# assume Bash
__RESH_PID="$BASHPID" # current pid
fi
# time
__RESH_TZ_BEFORE=$(date +%z)
# __RESH_RT_BEFORE="$EPOCHREALTIME"
__RESH_RT_BEFORE=$(__resh_get_epochrealtime)
if [ "$__RESH_VERSION" != "$(resh-collect -version)" ]; then
# shellcheck source=shellrc.sh
source ~/.resh/shellrc
if [ "$__RESH_VERSION" != "$(resh-collect -version)" ]; then
echo "RESH WARNING: You probably just updated RESH - PLEASE RESTART OR RELOAD THIS TERMINAL SESSION (resh version: $(resh-collect -version); resh version of this terminal session: ${__RESH_VERSION})"
else
echo "RESH INFO: New RESH shellrc script was loaded - if you encounter any issues please restart this terminal session."
fi
elif [ "$__RESH_REVISION" != "$(resh-collect -revision)" ]; then
# shellcheck source=shellrc.sh
source ~/.resh/shellrc
if [ "$__RESH_REVISION" != "$(resh-collect -revision)" ]; then
echo "RESH WARNING: You probably just updated RESH - PLEASE RESTART OR RELOAD THIS TERMINAL SESSION (resh revision: $(resh-collect -revision); resh revision of this terminal session: ${__RESH_REVISION})"
fi
fi
if [ "$__RESH_VERSION" = "$(resh-collect -version)" ] && [ "$__RESH_REVISION" = "$(resh-collect -revision)" ]; then
resh-collect -requireVersion "$__RESH_VERSION" \
-requireRevision "$__RESH_REVISION" \
-cmdLine "$__RESH_CMDLINE" \
-shell "$__RESH_SHELL" \
-uname "$__RESH_UNAME" \
-sessionId "$__RESH_SESSION_ID" \
-cols "$__RESH_COLS" \
-home "$__RESH_HOME" \
-lang "$__RESH_LANG" \
-lcAll "$__RESH_LC_ALL" \
-lines "$__RESH_LINES" \
-login "$__RESH_LOGIN" \
-pwd "$__RESH_PWD" \
-shellEnv "$__RESH_SHELL_ENV" \
-term "$__RESH_TERM" \
-pid "$__RESH_PID" \
-sessionPid "$__RESH_SESSION_PID" \
-host "$__RESH_HOST" \
-hosttype "$__RESH_HOSTTYPE" \
-ostype "$__RESH_OSTYPE" \
-machtype "$__RESH_MACHTYPE" \
-shlvl "$__RESH_SHLVL" \
-gitCdup "$__RESH_GIT_CDUP" \
-gitCdupExitCode "$__RESH_GIT_CDUP_EXIT_CODE" \
-gitRemote "$__RESH_GIT_REMOTE" \
-gitRemoteExitCode "$__RESH_GIT_REMOTE_EXIT_CODE" \
-realtimeBefore "$__RESH_RT_BEFORE" \
-realtimeSession "$__RESH_RT_SESSION" \
-realtimeSessSinceBoot "$__RESH_RT_SESS_SINCE_BOOT" \
-timezoneBefore "$__RESH_TZ_BEFORE" \
-osReleaseId "$__RESH_OS_RELEASE_ID" \
-osReleaseVersionId "$__RESH_OS_RELEASE_VERSION_ID" \
-osReleaseIdLike "$__RESH_OS_RELEASE_ID_LIKE" \
-osReleaseName "$__RESH_OS_RELEASE_NAME" \
-osReleasePrettyName "$__RESH_OS_RELEASE_PRETTY_NAME" \
&>~/.resh/collect_last_run_out.txt || echo "resh-collect ERROR: $(head -n 1 ~/.resh/collect_last_run_out.txt)"
fi
}
__resh_precmd() {
__RESH_EXIT_CODE=$?
__RESH_RT_AFTER=$(__resh_get_epochrealtime)
__RESH_TZ_AFTER=$(date +%z)
__RESH_PWD_AFTER="$PWD"
__RESH_GIT_CDUP_AFTER="$(git rev-parse --show-cdup 2>/dev/null)"
__RESH_GIT_CDUP_EXIT_CODE_AFTER=$?
__RESH_GIT_REMOTE_AFTER="$(git remote get-url origin 2>/dev/null)"
__RESH_GIT_REMOTE_EXIT_CODE_AFTER=$?
if [ -n "${__RESH_COLLECT}" ]; then
if [ "$__RESH_VERSION" != "$(resh-postcollect -version)" ]; then
# shellcheck source=shellrc.sh
source ~/.resh/shellrc
if [ "$__RESH_VERSION" != "$(resh-postcollect -version)" ]; then
echo "RESH WARNING: You probably just updated RESH - PLEASE RESTART OR RELOAD THIS TERMINAL SESSION (resh version: $(resh-collect -version); resh version of this terminal session: ${__RESH_VERSION})"
else
echo "RESH INFO: New RESH shellrc script was loaded - if you encounter any issues please restart this terminal session."
fi
elif [ "$__RESH_REVISION" != "$(resh-postcollect -revision)" ]; then
# shellcheck source=shellrc.sh
source ~/.resh/shellrc
if [ "$__RESH_REVISION" != "$(resh-postcollect -revision)" ]; then
echo "RESH WARNING: You probably just updated RESH - PLEASE RESTART OR RELOAD THIS TERMINAL SESSION (resh revision: $(resh-collect -revision); resh revision of this terminal session: ${__RESH_REVISION})"
fi
fi
if [ "$__RESH_VERSION" = "$(resh-postcollect -version)" ] && [ "$__RESH_REVISION" = "$(resh-postcollect -revision)" ]; then
resh-postcollect -requireVersion "$__RESH_VERSION" \
-requireRevision "$__RESH_REVISION" \
-cmdLine "$__RESH_CMDLINE" \
-realtimeBefore "$__RESH_RT_BEFORE" \
-exitCode "$__RESH_EXIT_CODE" \
-sessionId "$__RESH_SESSION_ID" \
-pwdAfter "$__RESH_PWD_AFTER" \
-gitCdupAfter "$__RESH_GIT_CDUP_AFTER" \
-gitCdupExitCodeAfter "$__RESH_GIT_CDUP_EXIT_CODE_AFTER" \
-gitRemoteAfter "$__RESH_GIT_REMOTE_AFTER" \
-gitRemoteExitCodeAfter "$__RESH_GIT_REMOTE_EXIT_CODE_AFTER" \
-realtimeAfter "$__RESH_RT_AFTER" \
-timezoneAfter "$__RESH_TZ_AFTER" \
&>~/.resh/postcollect_last_run_out.txt || echo "resh-postcollect ERROR: $(head -n 1 ~/.resh/postcollect_last_run_out.txt)"
fi
fi
unset __RESH_COLLECT
}
# do not add more hooks when shellrc is sourced again # do not add more hooks when shellrc is sourced again
if [ -z "${__RESH_PREEXEC_PRECMD_HOOKS_ADDED+x}" ]; then if [ -z "${__RESH_PREEXEC_PRECMD_HOOKS_ADDED+x}" ]; then

@ -0,0 +1,136 @@
# util.sh - resh utility functions
__resh_get_uuid() {
cat /proc/sys/kernel/random/uuid 2>/dev/null || resh-uuid
}
__resh_get_pid() {
if [ -n "$ZSH_VERSION" ]; then
# assume Zsh
local __RESH_PID="$$" # current pid
elif [ -n "$BASH_VERSION" ]; then
# assume Bash
local __RESH_PID="$BASHPID" # current pid
fi
echo "$__RESH_PID"
}
__resh_get_epochrealtime() {
if date +%s.%N | grep -vq 'N'; then
# GNU date
date +%s.%N
elif gdate --version >/dev/null && gdate +%s.%N | grep -vq 'N'; then
# GNU date take 2
gdate +%s.%N
elif [ -n "$ZSH_VERSION" ]; then
# zsh fallback using $EPOCHREALTIME
if [ -z "${__RESH_ZSH_LOADED_DATETIME+x}" ]; then
zmodload zsh/datetime
__RESH_ZSH_LOADED_DATETIME=1
fi
echo "$EPOCHREALTIME"
else
# dumb date
# XXX: we lost precison beyond seconds
date +%s
if [ -z "${__RESH_DATE_WARN+x}" ]; then
echo "resh WARN: can't get precise time - consider installing GNU date!"
__RESH_DATE_WARN=1
fi
fi
}
__resh_run_daemon() {
if [ -n "$ZSH_VERSION" ]; then
setopt LOCAL_OPTIONS NO_NOTIFY NO_MONITOR
fi
nohup resh-daemon &>~/.resh/daemon_last_run_out.txt & disown
}
__resh_bash_completion_init() {
local bash_completion_dir=~/.resh/bash_completion.d
# source user completion directory definitions
# taken from /usr/share/bash-completion/bash_completion
if [[ -d $bash_completion_dir && -r $bash_completion_dir && \
-x $bash_completion_dir ]]; then
for i in $(LC_ALL=C command ls "$bash_completion_dir"); do
i=$bash_completion_dir/$i
# shellcheck disable=SC2154
# shellcheck source=/dev/null
[[ ${i##*/} != @($_backup_glob|Makefile*|$_blacklist_glob) \
&& -f $i && -r $i ]] && . "$i"
done
fi
}
__resh_zsh_completion_init() {
# shellcheck disable=SC2206
fpath=(~/.resh/zsh_completion.d $fpath)
}
__resh_session_init() {
# posix
local __RESH_COLS="$COLUMNS"
local __RESH_LANG="$LANG"
local __RESH_LC_ALL="$LC_ALL"
# other LC ?
local __RESH_LINES="$LINES"
local __RESH_PWD="$PWD"
# non-posix
local __RESH_SHLVL="$SHLVL"
# pid
local __RESH_PID; __RESH_PID=$(__resh_get_pid)
# time
local __RESH_TZ_BEFORE; __RESH_TZ_BEFORE=$(date +%z)
local __RESH_RT_BEFORE; __RESH_RT_BEFORE=$(__resh_get_epochrealtime)
if [ "$__RESH_VERSION" != "$(resh-session-init -version)" ]; then
# shellcheck source=shellrc.sh
source ~/.resh/shellrc
if [ "$__RESH_VERSION" != "$(resh-session-init -version)" ]; then
echo "RESH WARNING: You probably just updated RESH - PLEASE RESTART OR RELOAD THIS TERMINAL SESSION (resh version: $(resh-session-init -version); resh version of this terminal session: ${__RESH_VERSION})"
else
echo "RESH INFO: New RESH shellrc script was loaded - if you encounter any issues please restart this terminal session."
fi
elif [ "$__RESH_REVISION" != "$(resh-session-init -revision)" ]; then
# shellcheck source=shellrc.sh
source ~/.resh/shellrc
if [ "$__RESH_REVISION" != "$(resh-session-init -revision)" ]; then
echo "RESH WARNING: You probably just updated RESH - PLEASE RESTART OR RELOAD THIS TERMINAL SESSION (resh revision: $(resh-session-init -revision); resh revision of this terminal session: ${__RESH_REVISION})"
fi
fi
if [ "$__RESH_VERSION" = "$(resh-session-init -version)" ] && [ "$__RESH_REVISION" = "$(resh-session-init -revision)" ]; then
resh-session-init -requireVersion "$__RESH_VERSION" \
-requireRevision "$__RESH_REVISION" \
-shell "$__RESH_SHELL" \
-uname "$__RESH_UNAME" \
-sessionId "$__RESH_SESSION_ID" \
-cols "$__RESH_COLS" \
-home "$__RESH_HOME" \
-lang "$__RESH_LANG" \
-lcAll "$__RESH_LC_ALL" \
-lines "$__RESH_LINES" \
-login "$__RESH_LOGIN" \
-shellEnv "$__RESH_SHELL_ENV" \
-term "$__RESH_TERM" \
-pid "$__RESH_PID" \
-sessionPid "$__RESH_SESSION_PID" \
-host "$__RESH_HOST" \
-hosttype "$__RESH_HOSTTYPE" \
-ostype "$__RESH_OSTYPE" \
-machtype "$__RESH_MACHTYPE" \
-shlvl "$__RESH_SHLVL" \
-realtimeBefore "$__RESH_RT_BEFORE" \
-realtimeSession "$__RESH_RT_SESSION" \
-realtimeSessSinceBoot "$__RESH_RT_SESS_SINCE_BOOT" \
-timezoneBefore "$__RESH_TZ_BEFORE" \
-osReleaseId "$__RESH_OS_RELEASE_ID" \
-osReleaseVersionId "$__RESH_OS_RELEASE_VERSION_ID" \
-osReleaseIdLike "$__RESH_OS_RELEASE_ID_LIKE" \
-osReleaseName "$__RESH_OS_RELEASE_NAME" \
-osReleasePrettyName "$__RESH_OS_RELEASE_PRETTY_NAME" \
&>~/.resh/session_init_last_run_out.txt || echo "resh-session-init ERROR: $(head -n 1 ~/.resh/session_init_last_run_out.txt)"
fi
}

@ -1,10 +1,28 @@
# shellcheck source=hooks.sh
. ~/.resh/hooks.sh
__resh_widget_arrow_up() { __resh_widget_arrow_up() {
return 0 (( __RESH_HISTNO++ ))
BUFFER="$(__resh_collect --recall --histno "$__RESH_HISTNO" 2> ~/.resh/arrow_up_last_run_out.txt)"
} }
__resh_widget_arrow_down() { __resh_widget_arrow_down() {
return 0 (( __RESH_HISTNO-- ))
BUFFER="$(__resh_collect --recall --histno "$__RESH_HISTNO" 2> ~/.resh/arrow_down_last_run_out.txt)"
} }
__resh_widget_control_R() { __resh_widget_control_R() {
return 0 # resh-collect --hstr
hstr
}
__resh_widget_arrow_up_compat() {
__bindfunc_compat_wrapper __resh_widget_arrow_up
}
__resh_widget_arrow_down_compat() {
__bindfunc_compat_wrapper __resh_widget_arrow_down
}
__resh_widget_control_R_compat() {
__bindfunc_compat_wrapper __resh_widget_control_R
} }
Loading…
Cancel
Save