Created
April 1, 2016 01:25
-
-
Save SomeCrazyGuy/e3b77251ae533b4ded2bafc880ba8262 to your computer and use it in GitHub Desktop.
A pager written entirely using bash 4 builtins, relies on no other system binaries.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash --noprofile | |
# DO ALMOST ANYTHING PUBLIC LICENSE | |
# Everyone is permitted to copy and distribute verbatim or modified | |
# copies of this code for any purpose as long as any "Credit" | |
# lines are not removed. | |
#Credit: /u/linuxversion | |
#<your Credit line here, if you want> | |
#extra strict flags | |
set -euo pipefail | |
#so I don't accidently forget whats builtin and whats not | |
PATH='' | |
#configuration options | |
declare -i cfg_line_numbers=1 | |
#globals | |
declare -a file_map | |
declare -i file_offset=0 | |
declare -i file_lines=0 | |
declare -i term_height=0 | |
declare -i term_width=0 | |
declare -i textarea_height=0 | |
declare -i textarea_line=0 | |
declare -i command_line=0 | |
#move the cursor to a specific row and colunm | |
function put_cursor() { | |
echo -en "\e[${1};${2}f" | |
} | |
#basically the same as the libncurses function of the same name | |
function mvprintw() { | |
local row="$1"; shift | |
local col="$1"; shift | |
printf "%s%s%s" $'\x1b[' "${row};${col}f" "$@" | |
} | |
#self-explanitory | |
function clear_screen() { | |
echo -en '\e[2J' | |
} | |
#erase text from command line to bottom of screen | |
function clear_command_line() { | |
mvprintw "$command_line" 0 $'\x1b[J' | |
} | |
function init_screen() { | |
#set terminal configuration to default | |
#echo -en '\ec' | |
#get the size of the terminal | |
put_cursor 999 999 | |
echo -en '\e[6n' | |
read -s -r -d'[' | |
read -s -r -d';' term_height | |
read -s -r -d'R' term_width | |
#do some math to position the various graphical elements | |
textarea_line=0 | |
textarea_height=$term_height | |
command_line=$term_height | |
clear_screen | |
put_cursor "$command_line" 0 | |
} | |
#draw text on the screen from memory with offset | |
function render_text() { | |
clear_screen | |
#figure out how many lines we can render | |
local modifier="$1" | |
local lines=$textarea_height | |
local last_screen=$((file_lines - textarea_height)) | |
file_offset=$((file_offset + modifier)) | |
[ $file_offset -gt $last_screen ] && file_offset=$last_screen | |
[ $file_offset -lt 0 ] && file_offset=0 | |
[ $lines -gt $file_lines ] && lines=$file_lines | |
#draw text in the viewing area | |
local fd_offset | |
local term_offset | |
for (( i=0; i<lines; ++i )) | |
do | |
fd_offset=$((i+file_offset)) | |
term_offset=$((i+textarea_line)) | |
[ $cfg_line_numbers -eq 1 ] && { | |
mvprintw "${term_offset}" 0 "${fd_offset}" | |
mvprintw "${term_offset}" 6 "${file_map[$fd_offset]}" | |
} || { | |
mvprintw "${term_offset}" 0 "${file_map[$fd_offset]}" | |
} | |
done | |
} | |
function main() { | |
#arg check | |
if (( $# > 0 )) && [ -f "$1" ] | |
then | |
mapfile file_map <"$1" | |
else | |
echo 'Usage: bash_pager <file>' | |
return 1 | |
fi | |
file_lines="${#file_map[@]}" | |
init_screen | |
render_text 0 | |
#read keys and perform actions | |
while read -s -r -N1 | |
do | |
case "$REPLY" in | |
( $'\x1b' ) #ESC pressed, handle sequence | |
read -s -r -N1 | |
case "$REPLY" in | |
( $'\x1b' ) #second escape, eval user input | |
read -e -r -p ': ' | |
set +eu | |
eval "$REPLY" | |
set -eu | |
;; | |
( '[' ) #arrow key or pgup/pgdown | |
read -s -r -N1 | |
case "$REPLY" in | |
( 'A' ) #arrow up | |
render_text -1 | |
;; | |
( 'B' ) #arrow down | |
render_text 1 | |
;; | |
( '5' ) #pgup | |
render_text "-$((textarea_height/2))" | |
;; | |
( '6' ) #pgdown | |
render_text "$((textarea_height/2))" | |
;; | |
esac | |
;; | |
esac | |
;; | |
( 'q' ) #quit | |
return 0 | |
;; | |
esac | |
#input keys have been read display results | |
clear_command_line | |
put_cursor "$command_line" 0 | |
done | |
} | |
main $@ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Good one, thanks for the effort