Compare commits

..

No commits in common. "master" and "v0.0.2" have entirely different histories.

18 changed files with 253 additions and 347 deletions

5
.gitattributes vendored
View file

@ -1,5 +0,0 @@
# Force text files to have unix eols, so Windows/Cygwin does not break them
*.* eol=lf
# Except for images because then on checkout the files have been altered.
*.png binary

View file

@ -2,23 +2,6 @@
### master
### v2.1.0, 2015-03-18
- `capture-pane` gets a `-J` flag. It joins wrapped lines and preserves trailing
spaces at each line's end.
- when capturing whole history, do not guess its size, but get it from
`#{history_limit}` format flag
### v2.0.0, 2015-03-14
- update readme
- extract default keys and key options to `variables.sh` file
- require tmux version 1.9 or greater to use the plugin
- change all internal variable names (BREAKING CHANGE!)
- change internal script names
- lot of internal refactoring
### v1.0.0, 2014-11-09
- improve `capture-pane`. It is now piped directly to the target file.
### v0.0.2, 2014-08-26
- add other plugins list to the README
- update readme to reflect github organization change

109
README.md
View file

@ -2,53 +2,77 @@
Features:
1. Logging of all output in the current pane<br/>
1. Enables logging of all output in the current pane<br/>
After you start logging, everything that's typed and all the output will be
saved to a file. Convenient for keeping track of your work.
2. Current pane "Screen Capture"<br/>
2. Enables "screen capture" of the current pane<br/>
All the text visible in the current pane is saved to a file. Like a
screenshot, but textual.
3. Save a complete history of current pane<br/>
3. Enables saving a complete history of the current pane<br/>
Everything that has been typed and all the output since the creation of the
current pane can be saved to a file.
4. Clear pane history with `prefix + alt + c`
Tested and working on Linux, OSX and Cygwin.
4. Clear pane history with `prefix + M-c`
### 1. Logging
Toggle (start/stop) logging in the current pane.
Key binding: `prefix + shift + p`<br/>
File path: `$HOME` (user home dir)<br/>
File name format:
* Key binding: `prefix + shift + p`
* File name format: `tmux-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log`
* File path: `$HOME` (user home dir)
* Example file: `~/tmux-my-session-0-1-20140527T165614.log`
tmux-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log
# Example file:
# tmux-my-session-0-1-20140527T165614.log
### 2. "Screen Capture"
Toggles (start/stop) logging in the current pane.
Save visible text, in the current pane. Equivalent of a "textual screenshot".
This feature improves the default `pipe-pane` logging mechanism by stripping
ANSI codes. This is how the plain `pipe-pane` log output looks like if you're
using terminal with coloring:
* Key binding: `prefix + alt + p`
* File name format: `tmux-screen-capture-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log`
* File path: `$HOME` (user home dir)
* Example file: `tmux-screen-capture-my-session-0-1-20140527T165614.log`
![garbled log output](/screenshots/garbled_log_output.png)
Garbled characters are called ANSI codes. They enable colors in terminal, but
are just making 'noise' in the textual log output.
A user will probably want to filter ANSI codes out of the log. Here's the same
log as above when this plugin is used:
![proper log output](/screenshots/proper_log_output.png)
### 2. "Screen capture"
Key binding: `prefix + alt + p`<br/>
File path: `$HOME` (user home dir)<br/>
File name format:
tmux-screen-capture-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log
# Example file:
# tmux-screen-capture-my-session-0-1-20140527T165614.log
Visible text in the current pane is saved to a file. Equivalent of a "texual
screenshot".
### 3. Save complete history
Save complete pane history to a file. Convenient if you retroactively remember
Key binding: `prefix + alt + shift + p`<br/>
File path: `$HOME` (user home dir)<br/>
File name format:
tmux-history-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log
# Example file:
# tmux-history-my-session-0-1-20140527T165614.log
Saves complete pane history to a file. Convenient if you retroactively remember
you need to log/save all the work.
* Key binding: `prefix + alt + shift + p`
* File name format: `tmux-history-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log`
* File path: `$HOME` (user home dir)
* Example file: `tmux-history-my-session-0-1-20140527T165614.log`
**NOTE**: this functionality depends on the value of `history-limit` - it
determines the number of lines Tmux keeps in the scrollback buffer. Everything
Tmux kept will also be saved to a file.
**NOTE**: this functionality depends on the value of `history-limit` - the number
of lines Tmux keeps in the scrollback buffer. Only what Tmux kept will also be saved,
to a file.
With modern computers it is ok to set this option to a high number:
Use `set -g history-limit 50000` in .tmux.conf, with modern computers
it is ok to set this option to a high number.
# in .tmux.conf
set -g history-limit 50000
### 4. Clear pane history
@ -60,7 +84,10 @@ This is just a convenience key binding.
Add plugin to the list of TPM plugins in `.tmux.conf`:
set -g @plugin 'tmux-plugins/tmux-logging'
set -g @tpm_plugins " \
tmux-plugins/tpm \
tmux-plugins/tmux-logging \
"
Hit `prefix + I` to fetch the plugin and source it.
@ -85,39 +112,19 @@ You should now have all `tmux-logging` key bindings defined.
### Installing `ansifilter` (recommended for OSX users)
If you're on OSX, it is recommended to install `ansifilter`:
`$ brew install ansifilter`
[ansifilter](http://www.andre-simon.de/doku/ansifilter/en/ansifilter.php)
is a program specialized for removing (or working with) ANSI codes.
If you're on OSX, it is recommened to install `ansifilter`:
`$ brew install ansifilter`
It helps with removing ANSI codes from the log. If `ansifilter` is not present,
ANSI codes are removed with `sed`.
This feature improves the default `pipe-pane` logging mechanism by stripping
ANSI codes. This is how the plain `pipe-pane` log output looks like if you're
using terminal with coloring:
![garbled log output](/screenshots/garbled_log_output.png)
Garbled characters are called ANSI codes. They enable colors in terminal, but
are just making 'noise' in the textual log output.
A user will probably want to filter ANSI codes out of the log. Here's the same
log as above when this plugin is used:
![proper log output](/screenshots/proper_log_output.png)
### Configuration Docs
- [Changing default options](docs/configuration.md).
### Other plugins
You might also find these useful:
- [resurrect](https://github.com/tmux-plugins/tmux-resurrect) - restore tmux
environment after system restart
- [pain control](https://github.com/tmux-plugins/tmux-pain-control) - useful standard
bindings for controlling panes
- [sessionist](https://github.com/tmux-plugins/tmux-sessionist) - lightweight

View file

@ -1,3 +0,0 @@
# Custom configuration
The default logging path is `$HOME` To change that, add `set -g @logging-path "path"` to `.tmux.conf` file

View file

@ -2,15 +2,37 @@
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/scripts/variables.sh"
source "$CURRENT_DIR/scripts/shared.sh"
source $CURRENT_DIR/scripts/shared.sh
default_pipe_pane_key="P" # Shift-p
default_pane_screenshot_key="M-p" # Alt-p
default_scrollback_dump_key="M-P" # Alt-Shift-p
default_clear_scrollback_key="M-c" # Alt-c
main() {
tmux bind-key "$logging_key" run-shell "$CURRENT_DIR/scripts/toggle_logging.sh"
tmux bind-key "$pane_screen_capture_key" run-shell "$CURRENT_DIR/scripts/screen_capture.sh"
tmux bind-key "$save_complete_history_key" run-shell "$CURRENT_DIR/scripts/save_complete_history.sh"
tmux bind-key "$clear_history_key" run-shell "$CURRENT_DIR/scripts/clear_history.sh"
setup_pipe_pane_key_binding() {
local key=$(get_tmux_option "@pipe_pane_key" "$default_pipe_pane_key")
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/tmux_proper_pipe_pane.sh"
}
setup_pane_screenshot_key_binding() {
local key=$(get_tmux_option "@pane_screenshot_key" "$default_pane_screenshot_key")
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/tmux_pane_screenshot.sh"
}
setup_scrollback_dump_key_binding() {
local key=$(get_tmux_option "@scrollback_dump_key" "$default_scrollback_dump_key")
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/tmux_scrollback_dump.sh"
}
setup_clear_scrollback_key_binding() {
local key=$(get_tmux_option "@scrollback_clear_key" "$default_clear_scrollback_key")
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/tmux_scrollback_clear.sh"
}
main() {
setup_pipe_pane_key_binding
setup_pane_screenshot_key_binding
setup_scrollback_dump_key_binding
setup_clear_scrollback_key_binding
}
main

View file

@ -0,0 +1,33 @@
# Variables in this helper should be set in the file sourcing the helper.
# Required variables:
# - path_option & default_path
# - name_option & default_name
get_path() {
get_tmux_option "$path_option" "$default_path"
}
# `tmux save-buffer` command does not perform interpolation, so we're doing it
# "manually" with `display-message`
get_filename() {
local name_template=$(get_tmux_option "$name_option" "$default_name")
tmux display-message -p "$name_template"
}
capture_pane() {
local file="$(get_path)/$(get_filename)"
local capture_scope=$1
if [ $capture_scope == "History" ]; then
# copying 9M lines back will hopefully fetch the whole scrollback
tmux capture-pane -S -9000000
elif [[ $capture_scope == "Screen capture" ]]; then
tmux capture-pane
else
# error
exit 1
fi
tmux save-buffer "$file"
tmux delete-buffer
remove_empty_lines_from_end_of_file "$file"
display_message "$capture_scope saved to $file"
}

View file

@ -1,78 +0,0 @@
#!/usr/bin/env bash
VERSION="$1"
UNSUPPORTED_MSG="$2"
get_tmux_option() {
local option=$1
local default_value=$2
local option_value=$(tmux show-option -gqv "$option")
if [ -z "$option_value" ]; then
echo "$default_value"
else
echo "$option_value"
fi
}
# Ensures a message is displayed for 5 seconds in tmux prompt.
# Does not override the 'display-time' tmux option.
display_message() {
local message="$1"
# display_duration defaults to 5 seconds, if not passed as an argument
if [ "$#" -eq 2 ]; then
local display_duration="$2"
else
local display_duration="5000"
fi
# saves user-set 'display-time' option
local saved_display_time=$(get_tmux_option "display-time" "750")
# sets message display time to 5 seconds
tmux set-option -gq display-time "$display_duration"
# displays message
tmux display-message "$message"
# restores original 'display-time' value
tmux set-option -gq display-time "$saved_display_time"
}
# this is used to get "clean" integer version number. Examples:
# `tmux 1.9` => `19`
# `1.9a` => `19`
get_digits_from_string() {
local string="$1"
local only_digits="$(echo "$string" | tr -dC '[:digit:]')"
echo "$only_digits"
}
tmux_version_int() {
local tmux_version_string=$(tmux -V)
echo "$(get_digits_from_string "$tmux_version_string")"
}
unsupported_version_message() {
if [ -n "$UNSUPPORTED_MSG" ]; then
echo "$UNSUPPORTED_MSG"
else
echo "Error, Tmux version unsupported! Please install Tmux version $VERSION or greater!"
fi
}
exit_if_unsupported_version() {
local current_version="$1"
local supported_version="$2"
if [ "$current_version" -lt "$supported_version" ]; then
display_message "$(unsupported_version_message)"
exit 1
fi
}
main() {
local supported_version_int="$(get_digits_from_string "$VERSION")"
local current_version_int="$(tmux_version_int)"
exit_if_unsupported_version "$current_version_int" "$supported_version_int"
}
main

View file

@ -1,14 +0,0 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/variables.sh"
source "$CURRENT_DIR/shared.sh"
main() {
if supported_tmux_version_ok; then
tmux clear-history
display_message "Pane history cleared!"
fi
}
main

View file

@ -1,17 +0,0 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/variables.sh"
source "$CURRENT_DIR/shared.sh"
main() {
if supported_tmux_version_ok; then
local file=$(expand_tmux_format_path "${save_complete_history_full_filename}")
local history_limit="$(tmux display-message -p -F "#{history_limit}")"
tmux capture-pane -J -S "-${history_limit}" -p > "${file}"
remove_empty_lines_from_end_of_file "${file}"
display_message "History saved to ${file}"
fi
}
main

View file

@ -1,16 +0,0 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/variables.sh"
source "$CURRENT_DIR/shared.sh"
main() {
if supported_tmux_version_ok; then
local file=$(expand_tmux_format_path "${screen_capture_full_filename}")
tmux capture-pane -J -p > "${file}"
remove_empty_lines_from_end_of_file "${file}"
display_message "Screen capture saved to ${file}"
fi
}
main

View file

@ -2,7 +2,7 @@ get_tmux_option() {
local option=$1
local default_value=$2
local option_value=$(tmux show-option -gqv "$option")
if [ -z "$option_value" ]; then
if [ -z $option_value ]; then
echo $default_value
else
echo $option_value
@ -39,17 +39,3 @@ remove_empty_lines_from_end_of_file() {
local temp=$(cat $file)
printf '%s\n' "$temp" > "$file"
}
supported_tmux_version_ok() {
$CURRENT_DIR/check_tmux_version.sh "$SUPPORTED_VERSION"
}
# Checking full path to logfile and expanding tmux format in normal path
# As example: expand %Y-%m-%d to current date
expand_tmux_format_path() {
local tmux_format_path=$1
local full_path=$(tmux display-message -p "${tmux_format_path}")
local full_directory_path=${full_path%/*}
mkdir -p "${full_directory_path}"
echo "${full_path}"
}

18
scripts/tmux_pane_screenshot.sh Executable file
View file

@ -0,0 +1,18 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Functions defined in capture_pane_helpers are customized via below variables.
default_path="$HOME"
default_name="tmux-screen-capture-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log"
path_option="@screenshot_path"
name_option="@screenshot_filename"
source $CURRENT_DIR/shared.sh
source $CURRENT_DIR/capture_pane_helpers.sh
main() {
capture_pane "Screen capture"
}
main

View file

@ -0,0 +1,70 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
default_log_path="$HOME"
default_log_name="tmux-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log"
log_path_option="@pipe_pane_path"
log_name_option="@pipe_pane_filename"
source $CURRENT_DIR/shared.sh
get_log_path() {
get_tmux_option "$log_path_option" "$default_log_path"
}
get_log_name() {
get_tmux_option "$log_name_option" "$default_log_name"
}
start_pipe_pane() {
local file="$(get_log_path)/$(get_log_name)"
$CURRENT_DIR/tmux_start_pipe_pane.sh "$file"
display_message "Started logging to $file"
}
stop_pipe_pane() {
local file="$(get_log_path)/$(get_log_name)"
tmux pipe-pane
display_message "Ended logging to $file"
}
# returns a string unique to current pane
pane_unique_id() {
tmux display-message -p "#{session_name}_#{window_index}_#{pane_index}"
}
# saving 'logging' 'not logging' status in a variable unique to pane
set_logging_variable() {
local value=$1
local pane_unique_id="$(pane_unique_id)"
tmux set-option -gq "@$pane_unique_id" "$value"
}
# this function checks if logging is happening for the current pane
is_logging() {
local pane_unique_id="$(pane_unique_id)"
local current_pane_logging=$(get_tmux_option "@$pane_unique_id" "not logging")
if [ $current_pane_logging == "logging" ]; then
return 0
else
return 1
fi
}
# starts/stop logging
toggle_pipe_pane() {
if is_logging; then
set_logging_variable "not logging"
stop_pipe_pane
else
set_logging_variable "logging"
start_pipe_pane
fi
}
main() {
toggle_pipe_pane
}
main

View file

@ -0,0 +1,11 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source $CURRENT_DIR/shared.sh
main() {
tmux clear-history
display_message "Pane history cleared!"
}
main

18
scripts/tmux_scrollback_dump.sh Executable file
View file

@ -0,0 +1,18 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Functions defined in capture_pane_helpers are customized via below variables.
default_path="$HOME"
default_name="tmux-history-#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log"
path_option="@scrollback_dump_path"
name_option="@scrollback_dump_filename"
source $CURRENT_DIR/shared.sh
source $CURRENT_DIR/capture_pane_helpers.sh
main() {
capture_pane "History"
}
main

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
# path to log file - global variable
FILE="$1"
# path to log file
file=$1
ansifilter_installed() {
type ansifilter >/dev/null 2>&1 || return 1
@ -12,33 +12,38 @@ system_osx() {
}
pipe_pane_ansifilter() {
tmux pipe-pane "exec cat - | ansifilter >> $FILE"
local file=$1
tmux pipe-pane "exec cat - | ansifilter >> $file"
}
pipe_pane_sed_osx() {
local file=$1
# Warning, very complex regex ahead.
# Some characters below might not be visible from github web view.
local ansi_codes_osx="(\[([0-9]{1,3}((;[0-9]{1,3})*)?)?[m|K]| |]0;[^]+|[[:space:]]+$)"
tmux pipe-pane "exec cat - | sed -E \"s/$ansi_codes_osx//g\" >> $FILE"
tmux pipe-pane "exec cat - | sed -E \"s/$ansi_codes_osx//g\" >> $file"
}
pipe_pane_sed() {
local file=$1
local ansi_codes="(\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]| )"
tmux pipe-pane "exec cat - | sed -r 's/$ansi_codes//g' >> $FILE"
tmux pipe-pane "exec cat - | sed -r 's/$ansi_codes//g' >> $file"
}
start_pipe_pane() {
local file=$1
if ansifilter_installed; then
pipe_pane_ansifilter
pipe_pane_ansifilter "$file"
elif system_osx; then
# OSX uses sed '-E' flag and a slightly different regex
pipe_pane_sed_osx
pipe_pane_sed_osx "$file"
else
pipe_pane_sed
pipe_pane_sed "$file"
fi
}
main() {
start_pipe_pane
local file=$1
start_pipe_pane "$file"
}
main
main "$file"

View file

@ -1,59 +0,0 @@
#!/usr/bin/env bash
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
source "$CURRENT_DIR/variables.sh"
source "$CURRENT_DIR/shared.sh"
start_pipe_pane() {
local file=$(expand_tmux_format_path "${logging_full_filename}")
"$CURRENT_DIR/start_logging.sh" "${file}"
display_message "Started logging to ${logging_full_filename}"
}
stop_pipe_pane() {
tmux pipe-pane
display_message "Ended logging to $logging_full_filename"
}
# returns a string unique to current pane
pane_unique_id() {
tmux display-message -p "#{session_name}_#{window_index}_#{pane_index}"
}
# saving 'logging' 'not logging' status in a variable unique to pane
set_logging_variable() {
local value="$1"
local pane_unique_id="$(pane_unique_id)"
tmux set-option -gq "@${pane_unique_id}" "$value"
}
# this function checks if logging is happening for the current pane
is_logging() {
local pane_unique_id="$(pane_unique_id)"
local current_pane_logging="$(get_tmux_option "@${pane_unique_id}" "not logging")"
if [ "$current_pane_logging" == "logging" ]; then
return 0
else
return 1
fi
}
# starts/stop logging
toggle_pipe_pane() {
if is_logging; then
set_logging_variable "not logging"
stop_pipe_pane
else
set_logging_variable "logging"
start_pipe_pane
fi
}
main() {
if supported_tmux_version_ok; then
toggle_pipe_pane
fi
}
main

View file

@ -1,55 +0,0 @@
SUPPORTED_VERSION="1.9"
# Key binding options and defaults
default_logging_key="P" # Shift-p
logging_key=$(tmux show-option -gqv "@logging_key")
logging_key=${logging_key:-$default_logging_key}
default_pane_screen_capture_key="M-p" # Alt-p
pane_screen_capture_key=$(tmux show-option -gqv "@screen-capture-key")
pane_screen_capture_key=${pane_screen_capture_key:-$default_pane_screen_capture_key}
default_save_complete_history_key="M-P" # Alt-Shift-p
save_complete_history_key=$(tmux show-option -gqv "@save-complete-history-key")
save_complete_history_key=${save_complete_history_key:-$default_save_complete_history_key}
default_clear_history_key="M-c" # Alt-c
clear_history_key=$(tmux show-option -gqv "@clear-history-key")
clear_history_key=${clear_history_key:-$default_clear_history_key}
# General options
filename_suffix="#{session_name}-#{window_index}-#{pane_index}-%Y%m%dT%H%M%S.log"
# Logging options
default_logging_path="$HOME"
logging_path=$(tmux show-option -gqv "@logging-path")
logging_path=${logging_path:-$default_logging_path}
default_logging_filename="tmux-${filename_suffix}"
logging_filename=$(tmux show-option -gqv "@logging-filename")
logging_filename=${logging_filename:-$default_logging_filename}
logging_full_filename="${logging_path}/${logging_filename}"
# Screen capture options
default_screen_capture_path="$HOME"
screen_capture_path=$(tmux show-option -gqv "@screen-capture-path")
screen_capture_path=${screen_capture_path:-$default_screen_capture_path}
default_screen_capture_filename="tmux-screen-capture-${filename_suffix}"
screen_capture_filename=$(tmux show-option -gqv "@screen-capture-filename")
screen_capture_filename=${screen_capture_filename:-$default_screen_capture_filename}
screen_capture_full_filename="${screen_capture_path}/${screen_capture_filename}"
# Save complete history options
default_save_complete_history_path="$HOME"
save_complete_history_path=$(tmux show-option -gqv "@save-complete-history-path")
save_complete_history_path=${save_complete_history_path:-$default_save_complete_history_path}
default_save_complete_history_filename="tmux-history-${filename_suffix}"
save_complete_history_filename=$(tmux show-option -gqv "@save-complete-history-filename")
save_complete_history_filename=${save_complete_history_filename:-$default_save_complete_history_filename}
save_complete_history_full_filename="${save_complete_history_path}/${save_complete_history_filename}"