Skip to content

Instantly share code, notes, and snippets.

@dubiouscript
Forked from SomeCrazyGuy/bash_pager.sh
Last active December 9, 2022 10:18
Show Gist options
  • Save dubiouscript/099efe99811bfe0a3b18a2911315eefe to your computer and use it in GitHub Desktop.
Save dubiouscript/099efe99811bfe0a3b18a2911315eefe to your computer and use it in GitHub Desktop.

Revisions

  1. dubiouscript revised this gist Dec 9, 2022. 1 changed file with 8 additions and 2 deletions.
    10 changes: 8 additions & 2 deletions bash_pager.sh
    Original file line number Diff line number Diff line change
    @@ -6,6 +6,7 @@
    # lines are not removed.

    #Credit: /u/linuxversion
    # add pipes : https://old.reddit.com/r/commandline/comments/4ct8px/i_wrote_a_pager_purely_in_bash_using_just_bash/d1lyq9q/
    #<your Credit line here, if you want>

    #extra strict flags
    @@ -103,7 +104,12 @@ function render_text() {

    function main() {
    #arg check
    if (( $# > 0 )) && [ -f "$1" ]
    # if (( $# > 0 )) && [ -f "$1" ]
    if (( $# == 0 ))
    then
    mapfile file_map
    exec < /dev/tty
    elif (( $# == 1 )) && [ -f "$1" ]
    then
    mapfile file_map <"$1"
    else
    @@ -159,4 +165,4 @@ function main() {
    done
    }

    main $@
    main $@
  2. @SomeCrazyGuy SomeCrazyGuy created this gist Apr 1, 2016.
    162 changes: 162 additions & 0 deletions bash_pager.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,162 @@
    #!/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 $@