#!/usr/bin/env bash #------------------------------------------------------------------------------ # Author E-Mail - terminalforlife@yahoo.com # Author GitHub - https://github.com/terminalforlife #------------------------------------------------------------------------------ Progrm=${0##*/} Usage(){ while read; do printf '%s\n' "$REPLY" done <<-EOF Usage: $Progrm [OPTS] [DIR_1 [DIR_2 ...]] -h, --help - Display this help information. -C, --no-color - Provide color via esscape sequences. -D, --no-subdirs - Ignore the 'sheets/_*' subdirectories. -I, --no-lenchk-line - Ignore the special 'lenchk=.*' line. -N, --no-preview - Omit the preview of each triggered line. -P, --no-pager - Do not use less(1) or more(1) for paging. -S, --no-summary - Omit the summary before $Progrm exits. -W, --no-whilelist - Do not use the whitelist file. -l, --limit [INT] - Override the limit of 80 columns. -w, --wl-file [FILE] - Use an alternative whitelist file. Additional directories can be appended to the argument string in order to process directories otherwise not handled by $Progrm. You can use '--' to let $Progrm know when to stop looking for flags. Files to whitelist must be placed line-by-line; one path per line. cheat.sheets/sheets/_perl/1line cheat.sheets/sheets/find The file paths to provide must begin with 'cheat.sheets/' to indicate the root of the repository, otherwise this feature will fail. The location of the whitelisting file ('$Progrm-excludes') must remain in the same directory in which $Progrm is stored, unless otherwise specified. Alternatively, a file can be whitelisted by ensuring the very first line contains only 'lenchk=disable', akin to a vim(1) modeline. EOF } Err(){ printf 'ERROR: %s\n' "$2" 1>&2 [ $1 -gt 0 ] && exit $1 } WLFile='lenchk-excludes' MaxCols=80 while [ "$1" ]; do case $1 in --) break ;; --help|-h|-\?) Usage; exit 0 ;; --limit|-l) shift; MaxCols=$1 if ! [[ $MaxCols =~ ^[0-9]+$ ]]; then Err 1 'Invalid column maximum provided.' fi ;; --no-pager|-P) NoPager='True' ;; --no-preview|-N) NoPreview='True' ;; --no-color|-C) NoColor='True' ;; --no-summary|-S) NoSummary='True' ;; --no-subdirs|-D) NoSubDirs='True' ;; --no-whitelist|-W) NoWhiteList='True' ;; -I|--no-lenchk-line) NoLenChkLine='True' ;; --wl-file|-w) shift if [ -z "$1" ]; then Err 1 'No alternative whitelist file provided.' else WLFile=$1 fi ;; -*) Err 1 'Incorrect option(s) specified.' ;; *) break ;; esac shift done # Thank you, Chubin. Feature apparently added in version 3.0 alpha, so should # be OK, but if anyone is having issues, just `cd` to the 'tests' directory. [ ${BASH_VERSINFO[0]:-0} -eq 3 ] || cd "${BASH_SOURCE[0]%/*}" &> /dev/null # Confirm we are in the right place. git rev-parse --is-inside-work-tree 1> /dev/null 2>&1 || Err 0 'Not inside a Git repository.' case $PWD in */cheat.sheets/tests) ;; '') Err 1 'Unable to determine the CWD.' ;; *) Err 1 "Not within the 'cheat.sheets/tests' directory." ;; esac Dirs=(../sheets/*) [ "$NoSubDirs" == 'True' ] || Dirs+=(../sheets/*/*) # Add user's own directories to check, if they exist. for ArgDir in "$@"; { if [ -d "$ArgDir" ]; then Dirs+=($ArgDir/*) else Err 1 "Directory '$ArgDir' not found." fi } # If the whitelist file exists, use it, unless whitelisting is disabled. # Keeping this test outside of the loop to avoid unnecessary processing. if [ "$NoWhiteList" != 'True' ] && [ -f "$WLFile" ]; then # Read the whitelist file, line-by-line, generating an array thereof. Whitelisted=() while read; do Whitelisted+=("../${REPLY#cheat.sheets/}") done < "$WLFile" fi # Using tput(1) for portability. if type -fP tput &> /dev/null; then C_Ellipses=`tput dim; tput setaf 7` C_LineNums=`tput bold; tput setaf 2` C_FileNames=`tput bold; tput setaf 1` C_Reset=`tput sgr0` else Err 1 'Unable to colorize output -- tput(1) not found.' fi Main(){ for File in "${Dirs[@]}"; { [ -f "$File" ] || continue # Per chubin's desire to have an "in-bound flag"; see #134. if [ "$NoLenChkLine" != 'True' ]; then SkipFile='False' readarray -t Buffer < "$File" for BufferLine in "${Buffer[@]}"; { if [[ $BufferLine == '# cheat.sh: '* ]]; then CheatLine=${BufferLine#'# cheat.sh: '} IFS=',' read -a Fields <<< "$CheatLine" for Field in "${Fields[@]}"; { [ "$Field" == "$Progrm=disable" ] && SkipFile='True' } fi } [ "$SkipFile" == 'True' ] && continue fi # If the current file matches one which is whitelisted, skip it. for CurWL in "${Whitelisted[@]}"; { [ "$File" == "$CurWL" ] && continue 2 } LineNum=0 HaveBeenHit='False' while read; do let LineNum++ # Ignore non-comment lines for '#' and '//'. case $REPLY in '#'*|'//'*) ;; *) continue ;; esac if [ ${#REPLY} -gt 80 ]; then # We only need to be informed of a hit just the once, per file. if [ "$HaveBeenHit" == 'False' ]; then # The leading newline character, if needed. [ "$NoPreview" == 'True' ] || printf '\n' # The filename containing problematic line lengths. [ "$NoColor" == 'True' ] || printf "$C_FileNames" printf '%s\n' "${File#../}" [ "$NoColor" == 'True' ] || printf "$C_Reset" HaveBeenHit='True' let Hits++ fi if ! [ "$NoPreview" == 'True' ]; then # The line number of the problematic length. [ "$NoColor" == 'True' ] || printf "$C_LineNums" printf ' %7d ' $LineNum # <-- allows for 9,999,999 lines. [ "$NoColor" == 'True' ] || printf "$C_Reset" # Cannot make this 80 columns long, due to the indentation # and padding, but if you need to test this, for the sake # of checking lenchk is doing its job, set the 70 to 80, - # then make sure the terminal window is wide enough. printf '%s' "${REPLY:0:70}" # Cut-off ellipses. [ "$NoColor" == 'True' ] || printf "$C_Ellipses" printf '...\n' [ "$NoColor" == 'True' ] || printf "$C_Reset" fi fi done < "$File" } if [ ${Hits:-0} -gt 0 -a "$NoSummary" != 'True' ]; then printf '\nFound %d file(s) with comment length >%d.\n'\ $Hits $MaxCols 1>&2 fi } if [ -t 1 -a "$NoPager" != 'True' ]; then # Prefer less(1), but have more(1) as a fallback. if type -fP less &> /dev/null; then Pager='less -R' elif type -fP more &> /dev/null; then Pager='more' if [ "$NoColor" != 'True' ]; then Err 1 'Only more(1) is available -- colors unsupported.' fi else Err 1 'Neither less(1) nor more(1) were found.' fi # Redirecting STDERR to address less(1) bug causing summary to display # where it shouldn't; only seems to happen when colorization is enabled. Main 2>&1 | $Pager else Main # Testing line for use when checking the summary lines up with wc(1). When # using this, be sure previewing is disabled and the summary is enabled. #printf '%d\n' $((`Main |& wc -l` - 2)) fi