Readme, fixes, changes

pull/184/head
Simon Let 3 years ago
parent 2b33598dde
commit 4f51e916c8
  1. 92
      README.md
  2. 4
      cmd/daemon/dump.go
  3. 38
      cmd/daemon/main.go
  4. 4
      cmd/daemon/record.go
  5. 4
      cmd/daemon/session-init.go
  6. 51
      installation.md
  7. 4
      internal/histfile/histfile.go
  8. 5
      internal/opt/opt.go
  9. 17
      internal/recio/read.go
  10. 26
      internal/searchapp/test.go
  11. 45
      roadmap.md
  12. 56
      scripts/install.sh
  13. 3
      scripts/resh-daemon-restart.sh
  14. 6
      scripts/resh-daemon-start.sh
  15. 31
      scripts/resh-daemon-stop.sh
  16. 2
      scripts/shellrc.sh
  17. 7
      scripts/test.sh
  18. 45
      troubleshooting.md

@ -19,68 +19,46 @@ Context-based replacement/enhancement for zsh and bash shell history
**Search your history by commands or arguments and get relevant results based on current directory, git repo, exit status, and device.** **Search your history by commands or arguments and get relevant results based on current directory, git repo, exit status, and device.**
## Installation ## Install with one command
### Prerequisites
Standard stuff: `bash(4.3+)`, `curl`, `tar`, ...
MacOS: `coreutils` (`brew install coreutils`)
### Simplest installation
Run this command.
```sh ```sh
curl -fsSL https://raw.githubusercontent.com/curusarn/resh/master/scripts/rawinstall.sh | bash curl -fsSL https://raw.githubusercontent.com/curusarn/resh/master/scripts/rawinstall.sh | sh
``` ```
### Simple installation You will need to have `curl` and `tar` installed.
Run
```shell More options on [Installation page](./installation.md)
git clone https://github.com/curusarn/resh.git
cd resh && scripts/rawinstall.sh
```
### Update ## Update
Check for updates and update
Once installed RESH can be updated using:
```sh ```sh
reshctl update reshctl update
``` ```
## Roadmap ## Search your history
[Overview of the features of the project](./roadmap.md)
## RESH SEARCH application
This is the most important part of this project. TODO: redo this
RESH SEARCH app searches your history by commands. It uses device, directories, git remote, and exit status to show you relevant results first. Draft:
See RESH in action - record a terminal video
All this context is not in the regular shell history. RESH records shell history with context to use it when searching. Recording content:
Search your history by commands - Show searching some longer command
At first, the search application will look something like this. Some history with context and most of it without. As you can see, you can still search the history just fine. Get results based on current context - Show getting project-specific commands
![resh search app](img/screen-resh-cli-v2-7-init.png) Find any command - Show searching where the context brings the relevant command to the top
Eventually most of your history will have context and RESH SEARCH app will get more useful. Start searching now - Show search in native shell histories
![resh search app](img/screen-resh-cli-v2-7.png)
Without a query, RESH SEARCH app shows you the latest history based on the current context (device, directory, git). Press CTRL+R to search.
Say bye to weak standard history search.
![resh search app](img/screen-resh-cli-v2-7-no-query.png)
RESH SEARCH app replaces the standard reverse search - launch it using Ctrl+R.
Enable/disable the Ctrl+R keybinding: TODO: This doesn't seem like the right place for keybindings
TODO: how to enable disable keybindings
### In-app key bindings ### In-app key bindings
@ -92,36 +70,8 @@ TODO: how to enable disable keybindings
- Ctrl+G to abort and paste the current query onto the command line - Ctrl+G to abort and paste the current query onto the command line
- Ctrl+R to switch between RAW and NORMAL mode - Ctrl+R to switch between RAW and NORMAL mode
### View the recorded history ## Issues & Ideas
FIXME: redo/update this section
Resh history is saved to: `~/.resh_history.json`
Each line is a versioned JSON that represents one executed command line.
This is how I view it `tail -f ~/.resh_history.json | jq` or `jq < ~/.resh_history.json`.
You can install `jq` using your favorite package manager or you can use other JSON parser to view the history.
![screenshot](img/screen.png)
*Recorded metadata will be reduced to only include useful information in the future.*
## Known issues
### Q: I use bash on macOS and resh doesn't work
**A:** Add line `[ -f ~/.bashrc ] && . ~/.bashrc` to your `~/.bash_profile`.
**Long Answer:** Under macOS bash shell only loads `~/.bash_profile` because every shell runs as login shell.
## Issues and ideas
Please do create issues if you encounter any problems or if you have suggestions: https://github.com/curusarn/resh/issues
## Uninstallation
You can uninstall this project at any time by running `rm -rf ~/.resh/`. Find help on [Troubleshooting page](./troubleshooting.md)
You won't lose any recorded history by removing `~/.resh` directory because history is saved in `~/.resh_history.json`. Still got an issue? Create an issue: https://github.com/curusarn/resh/issues

@ -2,7 +2,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"io/ioutil" "io"
"net/http" "net/http"
"github.com/curusarn/resh/internal/histfile" "github.com/curusarn/resh/internal/histfile"
@ -18,7 +18,7 @@ type dumpHandler struct {
func (h *dumpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { func (h *dumpHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
sugar := h.sugar.With(zap.String("endpoint", "/dump")) sugar := h.sugar.With(zap.String("endpoint", "/dump"))
sugar.Debugw("Handling request, reading body ...") sugar.Debugw("Handling request, reading body ...")
jsn, err := ioutil.ReadAll(r.Body) jsn, err := io.ReadAll(r.Body)
if err != nil { if err != nil {
sugar.Errorw("Error reading body", "error", err) sugar.Errorw("Error reading body", "error", err)
return return

@ -2,7 +2,6 @@ package main
import ( import (
"fmt" "fmt"
"io/ioutil"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
@ -22,7 +21,37 @@ var version string
var commit string var commit string
var development string var development string
const helpMsg = `ERROR: resh-daemon doesn't accept any arguments
WARNING:
You shouldn't typically need to start RESH daemon yourself.
Unless its already running, RESH daemon is started when a new terminal is opened.
RESH daemon will not start if it's already running even when you run it manually.
USAGE:
$ resh-daemon
Runs the daemon as foreground process. You can kill it with CTRL+C.
$ resh-daemon-start
Runs the daemon as background process detached from terminal.
LOGS & DEBUGGING:
Logs are located in:
${XDG_DATA_HOME}/resh/log.json (if XDG_DATA_HOME is set)
~/.local/share/resh/log.json (otherwise - more common)
A good way to see the logs as they are being produced is:
$ tail -f ~/.local/share/resh/log.json
MORE INFO:
https://github.com/curusarn/resh/
`
func main() { func main() {
if len(os.Args) > 1 {
fmt.Fprint(os.Stderr, helpMsg)
os.Exit(1)
}
config, errCfg := cfg.New() config, errCfg := cfg.New()
logger, err := logger.New("daemon", config.LogLevel, development) logger, err := logger.New("daemon", config.LogLevel, development)
if err != nil { if err != nil {
@ -83,7 +112,7 @@ func main() {
) )
} }
} }
err = ioutil.WriteFile(pidFile, []byte(strconv.Itoa(os.Getpid())), 0644) err = os.WriteFile(pidFile, []byte(strconv.Itoa(os.Getpid())), 0644)
if err != nil { if err != nil {
sugar.Fatalw("Could not create PID file", sugar.Fatalw("Could not create PID file",
"error", err, "error", err,
@ -116,7 +145,7 @@ type daemon struct {
} }
func (d *daemon) killDaemon(pidFile string) error { func (d *daemon) killDaemon(pidFile string) error {
dat, err := ioutil.ReadFile(pidFile) dat, err := os.ReadFile(pidFile)
if err != nil { if err != nil {
d.sugar.Errorw("Reading PID file failed", d.sugar.Errorw("Reading PID file failed",
"PIDFile", pidFile, "PIDFile", pidFile,
@ -128,8 +157,7 @@ func (d *daemon) killDaemon(pidFile string) error {
return fmt.Errorf("could not parse PID file contents: %w", err) return fmt.Errorf("could not parse PID file contents: %w", err)
} }
d.sugar.Infow("Successfully parsed PID", "PID", pid) d.sugar.Infow("Successfully parsed PID", "PID", pid)
cmd := exec.Command("kill", "-s", "sigint", strconv.Itoa(pid)) err = exec.Command("kill", "-SIGTERM", fmt.Sprintf("%d", pid)).Run()
err = cmd.Run()
if err != nil { if err != nil {
return fmt.Errorf("kill command finished with error: %w", err) return fmt.Errorf("kill command finished with error: %w", err)
} }

@ -2,7 +2,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"io/ioutil" "io"
"net/http" "net/http"
"github.com/curusarn/resh/internal/recordint" "github.com/curusarn/resh/internal/recordint"
@ -28,7 +28,7 @@ func (h *recordHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
sugar := h.sugar.With(zap.String("endpoint", "/record")) sugar := h.sugar.With(zap.String("endpoint", "/record"))
sugar.Debugw("Handling request, sending response, reading body ...") sugar.Debugw("Handling request, sending response, reading body ...")
w.Write([]byte("OK\n")) w.Write([]byte("OK\n"))
jsn, err := ioutil.ReadAll(r.Body) jsn, err := io.ReadAll(r.Body)
// run rest of the handler as goroutine to prevent any hangups // run rest of the handler as goroutine to prevent any hangups
go func() { go func() {
if err != nil { if err != nil {

@ -2,7 +2,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"io/ioutil" "io"
"net/http" "net/http"
"github.com/curusarn/resh/internal/recordint" "github.com/curusarn/resh/internal/recordint"
@ -19,7 +19,7 @@ func (h *sessionInitHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
sugar.Debugw("Handling request, sending response, reading body ...") sugar.Debugw("Handling request, sending response, reading body ...")
w.Write([]byte("OK\n")) w.Write([]byte("OK\n"))
// TODO: should we somehow check for errors here? // TODO: should we somehow check for errors here?
jsn, err := ioutil.ReadAll(r.Body) jsn, err := io.ReadAll(r.Body)
// run rest of the handler as goroutine to prevent any hangups // run rest of the handler as goroutine to prevent any hangups
go func() { go func() {
if err != nil { if err != nil {

@ -0,0 +1,51 @@
# Installation
## One command installation
Feel free to check the `rawinstall.sh` script before running it.
```sh
curl -fsSL https://raw.githubusercontent.com/curusarn/resh/master/scripts/rawinstall.sh | sh
```
You will need to have `curl` and `tar` installed.
## Update
Once installed RESH can be updated using:
```sh
reshctl update
```
## Clone & Install
```sh
git clone https://github.com/curusarn/resh.git
cd resh
scripts/rawinstall.sh
```
## Build from source
:warning: Building from source is intended for development and troubleshooting.
```sh
git clone https://github.com/curusarn/resh.git
cd resh
make install
```
## Uninstallation
You can uninstall RESH by running: `rm -rf ~/.resh/`.
Restart your terminal after uninstall.
### Installed files
Binaries and shell files are in: `~/.resh/`
Recorded history, device files, and logs are in: `~/.local/share/resh/` (or `${XDG_DATA_HOME}/resh/`)
RESH config file is in: `~/.config/resh.toml`
Also check your `~/.zshrc` and `~/.bashrc`.
RESH adds a necessary line there to load itself on terminal startup.

@ -100,7 +100,7 @@ func (h *Histfile) loadHistory(bashHistoryPath, zshHistoryPath string, maxInitHi
) )
history, err := h.rio.ReadAndFixFile(h.historyPath, 3) history, err := h.rio.ReadAndFixFile(h.historyPath, 3)
if err != nil { if err != nil {
h.sugar.Panicf("Failed to read file: %w", err) h.sugar.Fatalf("Failed to read history file: %v", err)
} }
h.sugar.Infow("Resh history loaded from file", h.sugar.Infow("Resh history loaded from file",
"historyFile", h.historyPath, "historyFile", h.historyPath,
@ -113,7 +113,7 @@ func (h *Histfile) loadHistory(bashHistoryPath, zshHistoryPath string, maxInitHi
h.sugar.Infow("Resh history loaded and processed", h.sugar.Infow("Resh history loaded and processed",
"recordCount", len(reshCmdLines.List), "recordCount", len(reshCmdLines.List),
) )
if useNativeHistories == false { if !useNativeHistories {
h.bashCmdLines = reshCmdLines h.bashCmdLines = reshCmdLines
h.zshCmdLines = histlist.Copy(reshCmdLines) h.zshCmdLines = histlist.Copy(reshCmdLines)
return return

@ -1,6 +1,7 @@
package opt package opt
import ( import (
"fmt"
"os" "os"
"github.com/curusarn/resh/internal/output" "github.com/curusarn/resh/internal/output"
@ -17,10 +18,10 @@ func HandleVersionOpts(out *output.Output, args []string, version, commit string
// and adding "more correct" variants would mean supporting more variants. // and adding "more correct" variants would mean supporting more variants.
switch os.Args[1] { switch os.Args[1] {
case "-version": case "-version":
out.Info(version) fmt.Print(version)
os.Exit(0) os.Exit(0)
case "-revision": case "-revision":
out.Info(commit) fmt.Print(commit)
os.Exit(0) os.Exit(0)
case "-requireVersion": case "-requireVersion":
if len(os.Args) < 3 { if len(os.Args) < 3 {

@ -22,18 +22,21 @@ func (r *RecIO) ReadAndFixFile(fpath string, maxErrors int) ([]record.V1, error)
numErrs := len(decodeErrs) numErrs := len(decodeErrs)
if numErrs > maxErrors { if numErrs > maxErrors {
r.sugar.Errorw("Encountered too many decoding errors", r.sugar.Errorw("Encountered too many decoding errors",
"corruptedRecords", numErrs, "errorsCount", numErrs,
"individualErrors", "<Search 'Error while decoding line' to see individual errors>",
) )
return nil, fmt.Errorf("encountered too many decoding errors") return nil, fmt.Errorf("encountered too many decoding errors, last error: %w", decodeErrs[len(decodeErrs)-1])
} }
if numErrs == 0 { if numErrs == 0 {
return recs, nil return recs, nil
} }
// TODO: check the error messages r.sugar.Warnw("Some history records could not be decoded - fixing RESH history file by dropping them",
r.sugar.Warnw("Some history records could not be decoded - fixing resh history file by dropping them",
"corruptedRecords", numErrs, "corruptedRecords", numErrs,
"lastError", decodeErrs[len(decodeErrs)-1],
"individualErrors", "<Search 'Error while decoding line' to see individual errors>",
) )
fpathBak := fpath + ".bak" fpathBak := fpath + ".bak"
r.sugar.Infow("Backing up current corrupted history file", r.sugar.Infow("Backing up current corrupted history file",
"historyFileBackup", fpathBak, "historyFileBackup", fpathBak,
@ -93,13 +96,13 @@ func (r *RecIO) ReadFile(fpath string) ([]record.V1, []error, error) {
} }
recs = append(recs, *rec) recs = append(recs, *rec)
} }
r.sugar.Infow("Loaded resh history records",
"recordCount", len(recs),
)
if err != io.EOF { if err != io.EOF {
r.sugar.Error("Error while reading file", zap.Error(err)) r.sugar.Error("Error while reading file", zap.Error(err))
return recs, decodeErrs, err return recs, decodeErrs, err
} }
r.sugar.Infow("Loaded resh history records",
"recordCount", len(recs),
)
return recs, decodeErrs, nil return recs, decodeErrs, nil
} }

@ -1,26 +0,0 @@
package searchapp
import (
"github.com/curusarn/resh/internal/histcli"
"github.com/curusarn/resh/internal/msg"
"github.com/curusarn/resh/internal/recio"
"go.uber.org/zap"
)
// LoadHistoryFromFile ...
func LoadHistoryFromFile(sugar *zap.SugaredLogger, historyPath string, numLines int) msg.CliResponse {
rio := recio.New(sugar)
recs, _, err := rio.ReadFile(historyPath)
if err != nil {
sugar.Panicf("failed to read history file: %w", err)
}
if numLines != 0 && numLines < len(recs) {
recs = recs[:numLines]
}
cliRecords := histcli.New(sugar)
for i := len(recs) - 1; i >= 0; i-- {
rec := recs[i]
cliRecords.AddRecord(&rec)
}
return msg.CliResponse{Records: cliRecords.List}
}

@ -1,45 +0,0 @@
# RESH Roadmap
| | Legend |
| --- | --- |
| :heavy_check_mark: | Implemented |
| :white_check_mark: | Implemented but I'm not happy with it |
| :x: | Not implemented |
*NOTE: Features can change in the future*
TODO: Update this
- :heavy_check_mark: Record shell history with metadata
- :heavy_check_mark: save it as JSON to `~/.resh_history.json`
- :white_check_mark: Provide an app to search the history
- :heavy_check_mark: launch with CTRL+R (enable it using `reshctl enable ctrl_r_binding_global`)
- :heavy_check_mark: search by keywords
- :heavy_check_mark: relevant results show up first based on context (host, directory, git, exit status)
- :heavy_check_mark: allow searching completely without context ("raw" mode)
- :heavy_check_mark: import and search history from before RESH was installed
- :white_check_mark: include a help with keybindings
- :x: allow listing details for individual commands
- :x: allow explicitly searching by metadata
- :heavy_check_mark: Provide a `reshctl` utility to control and interact with the project
- :heavy_check_mark: turn on/off resh key bindings
- :heavy_check_mark: zsh completion
- :heavy_check_mark: bash completion
- :x: Multi-device history
- :x: Synchronize recorded history between devices
- :x: Allow proxying history when ssh'ing into remote servers
- :x: Provide a stable API to make resh extensible
- :heavy_check_mark: Support zsh and bash
- :heavy_check_mark: Support Linux and macOS
- :white_check_mark: Require only essential prerequisite software
- :heavy_check_mark: Linux
- :white_check_mark: MacOS *(requires coreutils - `brew install coreutils`)*

@ -1,6 +1,4 @@
#!/usr/bin/env bash #!/usr/bin/env sh
# TODO: Swith to sh shebang?
set -euo pipefail set -euo pipefail
@ -12,11 +10,11 @@ echo
echo "Checking your system ..." echo "Checking your system ..."
printf '\e[31;1m' # red color on printf '\e[31;1m' # red color on
reset() { cleanup() {
printf '\e[0m' # reset printf '\e[0m' # reset
exit exit
} }
trap reset EXIT INT TERM trap cleanup EXIT INT TERM
# /usr/bin/zsh -> zsh # /usr/bin/zsh -> zsh
login_shell=$(echo "$SHELL" | rev | cut -d'/' -f1 | rev) login_shell=$(echo "$SHELL" | rev | cut -d'/' -f1 | rev)
@ -35,9 +33,6 @@ fi
# TODO: Explicitly ask users if they want to enable RESH in shells # TODO: Explicitly ask users if they want to enable RESH in shells
# Only offer shells with supported versions # Only offer shells with supported versions
# E.g. Enable RESH in: Zsh (your login shell), Bash, Both shells # E.g. Enable RESH in: Zsh (your login shell), Bash, Both shells
# TODO: V3: We already partially have these checks in `reshctl doctor`
# figure out if we want to redo this in v3 or not
# the login shell logic is flawed
bash_version=$(bash -c 'echo ${BASH_VERSION}') bash_version=$(bash -c 'echo ${BASH_VERSION}')
bash_version_major=$(bash -c 'echo ${BASH_VERSINFO[0]}') bash_version_major=$(bash -c 'echo ${BASH_VERSINFO[0]}')
@ -87,28 +82,13 @@ printf '\e[0m' # reset
# # shellcheck disable=2034 # # shellcheck disable=2034
# read -r x # read -r x
# Shutting down resh daemon ... if [ -z "${__RESH_VERSION-}" ]; then
echo "Stopping RESH daemon ..." # First installation
pid_file="${XDG_DATA_HOME-~/.local/share}/resh/daemon.pid" # Stop the daemon anyway just to be sure
if [ ! -f "$pid_file" ]; then # But don't output anything
# Use old pid file location ./scripts/resh-daemon-stop.sh -q
pid_file=~/.resh/resh.pid
fi
failed_to_kill() {
# Do not print error during first installation
if [ -n "${__RESH_VERSION-}" ]; then
echo "ERROR: Failed to kill the resh-daemon - maybe it wasn't running?"
fi
}
if [ -f "$pid_file" ]; then
pid=$(cat "$pid_file")
kill -SIGTERM "$pid" || failed_to_kill
rm "$pid_file"
else else
killall -SIGTERM resh-daemon || failed_to_kill ./scripts/resh-daemon-stop.sh
fi fi
echo "Installing ..." echo "Installing ..."
@ -143,6 +123,8 @@ cp -f submodules/bash-zsh-compat-widgets/bindfunc.sh ~/.resh/bindfunc.sh
cp -f scripts/shellrc.sh ~/.resh/shellrc cp -f scripts/shellrc.sh ~/.resh/shellrc
cp -f scripts/resh-daemon-start.sh ~/.resh/bin/resh-daemon-start cp -f scripts/resh-daemon-start.sh ~/.resh/bin/resh-daemon-start
cp -f scripts/resh-daemon-stop.sh ~/.resh/bin/resh-daemon-stop
cp -f scripts/resh-daemon-restart.sh ~/.resh/bin/resh-daemon-restart
cp -f scripts/hooks.sh ~/.resh/ cp -f scripts/hooks.sh ~/.resh/
cp -f scripts/rawinstall.sh ~/.resh/ cp -f scripts/rawinstall.sh ~/.resh/
@ -161,10 +143,10 @@ if [ "$bash_ok" = 1 ]; then
fi fi
# Adding resh shellrc to .bashrc ... # Adding resh shellrc to .bashrc ...
grep -q '[[ -f ~/.resh/shellrc ]] && source ~/.resh/shellrc' ~/.bashrc ||\ grep -q '[[ -f ~/.resh/shellrc ]] && source ~/.resh/shellrc' ~/.bashrc ||\
echo -e '\n[[ -f ~/.resh/shellrc ]] && source ~/.resh/shellrc # this line was added by RESH (REcycle SHell)' >> ~/.bashrc echo -e '\n[[ -f ~/.resh/shellrc ]] && source ~/.resh/shellrc # this line was added by RESH' >> ~/.bashrc
# Adding bash-preexec to .bashrc ... # Adding bash-preexec to .bashrc ...
grep -q '[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh' ~/.bashrc ||\ grep -q '[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh' ~/.bashrc ||\
echo -e '\n[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh # this line was added by RESH (REcycle SHell)' >> ~/.bashrc echo -e '\n[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh # this line was added by RESH' >> ~/.bashrc
fi fi
# Only add shell directives into zsh if it passed version checks # Only add shell directives into zsh if it passed version checks
@ -172,11 +154,10 @@ if [ "$zsh_ok" = 1 ]; then
# Adding resh shellrc to .zshrc ... # Adding resh shellrc to .zshrc ...
if [ -f ~/.zshrc ]; then if [ -f ~/.zshrc ]; then
grep -q '[ -f ~/.resh/shellrc ] && source ~/.resh/shellrc' ~/.zshrc ||\ grep -q '[ -f ~/.resh/shellrc ] && source ~/.resh/shellrc' ~/.zshrc ||\
echo -e '\n[ -f ~/.resh/shellrc ] && source ~/.resh/shellrc # this line was added by RESH (REcycle SHell)' >> ~/.zshrc echo -e '\n[ -f ~/.resh/shellrc ] && source ~/.resh/shellrc # this line was added by RESH' >> ~/.zshrc
fi fi
fi fi
echo "Starting RESH daemon ..."
~/.resh/bin/resh-daemon-start ~/.resh/bin/resh-daemon-start
printf ' printf '
@ -202,18 +183,23 @@ RESH HISTORY SEARCH
Searches your history by commands. Searches your history by commands.
Device, directories, git remote, and exit status is used to display relevant results first. Device, directories, git remote, and exit status is used to display relevant results first.
At first, RESH SEARCH will use the standard shell history without context. At first, RESH SEARCH will use bash/zsh history without context.
All history recorded from now on will have context which will be used by the RESH SEARCH. All history recorded from now on will have context which will be used by the RESH SEARCH.
CHECK FOR UPDATES CHECK FOR UPDATES
To check for (and install) updates use reshctl command: To check for (and install) updates use:
$ reshctl update $ reshctl update
' '
# TODO: recorded history section would be better in github readme
printf " printf "
RECORDED HISTORY RECORDED HISTORY
Your resh history will be recorded to '${XDG_DATA_HOME-~/.local/share}/resh/history.reshjson' Your resh history will be recorded to '${XDG_DATA_HOME-~/.local/share}/resh/history.reshjson'
Look at it using e.g. following command (you might need to install jq) Look at it using e.g. following command (you might need to install jq)
$ cat ${XDG_DATA_HOME-~/.local/share}/resh/history.reshjson | sed 's/^v[^{]*{/{/' | jq . $ cat ${XDG_DATA_HOME-~/.local/share}/resh/history.reshjson | sed 's/^v[^{]*{/{/' | jq .
LOGS
RESH logs to '${XDG_DATA_HOME-~/.local/share}/resh/log.json'
Logs are useful for troubleshooting issues.
" "
printf ' printf '
ISSUES & FEEDBACK ISSUES & FEEDBACK

@ -0,0 +1,3 @@
#!/usr/bin/env sh
resh-daemon-stop "$@"
resh-daemon-start "$@"

@ -1,4 +1,8 @@
#! /usr/bin/env sh #!/usr/bin/env sh
if [ "${1-}" != "-q" ]; then
echo "Starting RESH daemon ..."
printf "Logs are in: %s\n" "${XDG_DATA_HOME-~/.local/share}/resh/log.json"
fi
# Run daemon in background - don't block # Run daemon in background - don't block
# Redirect stdin, stdout, and stderr to /dev/null - detach all I/O # Redirect stdin, stdout, and stderr to /dev/null - detach all I/O
resh-daemon </dev/null >/dev/null 2>/dev/null & resh-daemon </dev/null >/dev/null 2>/dev/null &

@ -0,0 +1,31 @@
#!/usr/bin/env sh
failed_to_kill() {
[ "${1-}" != "-q" ] && echo "Failed to kill the RESH daemon - it probably isn't running"
}
xdg_pid() {
local path="${XDG_DATA_HOME-}"/resh/daemon.pid
[ -n "${XDG_DATA_HOME-}" ] && [ -f "$path" ] || return 1
cat "$path"
}
default_pid() {
local path=~/.local/share/resh/daemon.pid
[ -f "$path" ] || return 1
cat "$path"
}
legacy_pid() {
local path=~/.resh/resh.pid
[ -f "$path" ] || return 1
cat "$path"
}
pid=$(xdg_pid || default_pid || legacy_pid)
if [ -n "$pid" ]; then
[ "${1-}" != "-q" ] && printf "Stopping RESH daemon ... (PID: %s)\n" "$pid"
kill "$pid" || failed_to_kill
else
[ "${1-}" != "-q" ] && printf "Stopping RESH daemon ...\n"
killall -q resh-daemon || failed_to_kill
fi

@ -17,7 +17,7 @@ fi
# shellcheck disable=2155 # shellcheck disable=2155
export __RESH_VERSION=$(resh-collect -version) export __RESH_VERSION=$(resh-collect -version)
resh-daemon-start resh-daemon-start -q
[ "$(resh-config --key BindControlR)" = true ] && __resh_bind_control_R [ "$(resh-config --key BindControlR)" = true ] && __resh_bind_control_R

@ -1,9 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env sh
# very simple tests to catch simple errors in scripts # very simple tests to catch simple errors in scripts
# shellcheck disable=SC2016
[ "${BASH_SOURCE[0]}" != "scripts/test.sh" ] && echo 'Run this script using `make test`' && exit 1
for f in scripts/*.sh; do for f in scripts/*.sh; do
echo "Running shellcheck on $f ..." echo "Running shellcheck on $f ..."
shellcheck "$f" --shell=bash --severity=error || exit 1 shellcheck "$f" --shell=bash --severity=error || exit 1
@ -14,7 +11,7 @@ for f in scripts/{shellrc,hooks}.sh; do
! zsh -n "$f" && echo "Zsh syntax check failed!" && exit 1 ! zsh -n "$f" && echo "Zsh syntax check failed!" && exit 1
done done
if [ "$1" == "--all" ]; then if [ "$1" = "--all" ]; then
for sh in bash zsh; do for sh in bash zsh; do
echo "Running functions in scripts/shellrc.sh using $sh ..." echo "Running functions in scripts/shellrc.sh using $sh ..."
! $sh -c ". scripts/shellrc.sh; __resh_preexec; __resh_precmd" && echo "Error while running functions!" && exit 1 ! $sh -c ". scripts/shellrc.sh; __resh_preexec; __resh_precmd" && echo "Error while running functions!" && exit 1

@ -0,0 +1,45 @@
# Troubleshooting
## First help
Run RESH doctor to detect common issues:
```sh
reshctl doctor
```
## Restarting RESH daemon
Sometimes restarting RESH daemon can help:
```sh
resh-daemon-restart
```
Two more useful commands:
```sh
resh-daemon-start
resh-daemon-stop
```
:warning: You will get error messages in your shell when RESH daemon is not running.
## Logs
## Disabling RESH
If you have a persistent issue with RESH you can temporarily disable it.
Go to `~/.zshrc` and `~/.bashrc` and comment out following lines:
```sh
[[ -f ~/.resh/shellrc ]] && source ~/.resh/shellrc
[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh # bashrc only
```
The second line is bash-specific so you won't find it in `~/.zshrc`
### RESH in bash on macOS doesn't work
**A:** Add line `[ -f ~/.bashrc ] && . ~/.bashrc` to your `~/.bash_profile`.
**Long Answer:** Under macOS bash shell only loads `~/.bash_profile` because every shell runs as login shell.
Loading…
Cancel
Save