Skip to content

Instantly share code, notes, and snippets.

@sebastiancarlos
Last active March 22, 2024 20:18
Show Gist options
  • Save sebastiancarlos/b8f2d449c92d21443cd54569acf22053 to your computer and use it in GitHub Desktop.
Save sebastiancarlos/b8f2d449c92d21443cd54569acf22053 to your computer and use it in GitHub Desktop.
sqlite3h - Wrapper around sqlite3 which saves interactive session to a history file
#! /usr/bin/env bash
# All my gist code is licensed under the MIT license.
### UPDATE!
# I noticed that this entire solution is unnecessary, as the following
# produces the same result, and can be put in the sqlite start file.
# ```
# .echo on
# .output "| tee -a history.txt"
# ```
# sqlite3h
# - "sqlite3 history"
# - Wrapper around sqlite3 which appends interactive session to a file
# - Unlike ".output | tee -a history.txt" which only appends the output, and
# ".sqlite_history" which only stores the command, this stores both.
history_file="/tmp/sqlite3_history.txt"
tmp_history_file="/tmp/sqlite3_history_tmp.txt"
tmp_history_file_plain="/tmp/sqlite3_history_tmp_plain.txt"
# create history file it doesn't exist
if [[ ! -f "$history_file" ]]; then
touch "$history_file"
fi
# if history files still exist, bail out.
# this probably means that the previous post-processing is still running.
if [[ -f "$tmp_history_file" || -f "$tmp_history_file_plain" ]]; then
echo "History files still exist. Please wait for the previous post-processing to finish."
exit 1
fi
sqlite3 "$@" | tee "$tmp_history_file"
( # start a subshell to post-process in the background
# process tmp history file in a virtual terminal to convert to plain text
term2plain "$tmp_history_file" >> "$tmp_history_file_plain"
# process file by removing everything before the "sqlite>" prompts (could be
# a custom readline prompt)
sed -i -E 's/^(.*)sqlite>/sqlite>/g' "$tmp_history_file_plain"
# append to history file
cat "$tmp_history_file_plain" >> "$history_file"
# remove temporary files
/usr/bin/rm -f "$tmp_history_file" "$tmp_history_file_plain"
) & # end subshell
#! /usr/bin/env bash
# All my gist code is licensed under the MIT license.
# term2plain
# - Convert a text file containing terminal escape sequences to plain text.
# - This plain text is close to the visual result of running the file in a
# terminal.
# - This is achieved by running the file in a virtual terminal (tmux) and
# capturing it's buffer output.
# - For simple escape sequences like color, this might be overkill, but it's
# useful for interactive programs which read user input, and the cursor
# move sequences must be interpreted to produce the final input.
# - Example:
# $ interactive-program | tee output.txt # works for simple ones like
# # sqlite or gdb, not vim
# $ term2plain output.txt
# $ vim output.txt # see the plain-text output after escape sequences were
# # processed by a virtual terminal.
# Store the file path and the name for the tmux session
file_path="$1"
session_name="term2plain_session"
output="/tmp/term2plain_output.txt"
start_marker="#term2plain-start"
end_marker="#term2plain-end"
SLEEP_TIME=0.1 # adjust sleep as needed based on file size
# bail if tmux is not installed
if ! command -v tmux &> /dev/null; then
echo "Error: tmux is not installed"
exit 1
fi
# Create a new detached tmux session
tmux new-session -d -s "$session_name"
# Send the 'cat' command to the session
tmux send-keys -t "$session_name" "cat '$file_path'" ' \' C-m "$start_marker" C-m
# Wait a little to make sure 'cat' has finished
sleep $SLEEP_TIME
# type end marker
tmux send-keys -t "$session_name" "$end_marker" C-m
# Capture the pane output
tmux capture-pane -pS - -t "$session_name" >| "$output"
# Kill the tmux session
tmux kill-session -t "$session_name"
# remove everything before and after markers
sed -i -e '1,/'"${start_marker}"'/d' "$output"
sed -i -e '/'"${end_marker}"'/,$d' "$output"
# Print the captured output
cat "$output"
/usr/bin/rm "$output"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment