diff --git a/README.md b/README.md index 4962e06..94cea95 100644 --- a/README.md +++ b/README.md @@ -416,7 +416,9 @@ This pulls down the latest image with baked in cheatsheets and starts the app an ## Editors integration -You can use *cheat.sh* directly from the editor (*Vim*, *Emacs* and *Visual Studio Code* are currently supported). +You can use *cheat.sh* directly from the editor +(*Emacs*, *Sublime*, *Vim*, and *Visual Studio Code* are currently supported; +not all features are supported by all plugins though; see below). Instead of opening your browser, googling, browsing Stack Overflow and eventually copying the code snippets you need into the clipboard and later pasting them into the editor, @@ -439,6 +441,18 @@ If you use some static analysis plugin such as *syntastic* (for Vim), you can us its warning and error messages as cheat.sh queries: place the cursor on the problem line and press `KE`: explanation for the warning will be opened in a new buffer. +Features supported by cheat.sh plugins for different editors: + +|Feature |Emacs|Sublime|Vim|VSCode| +|-------------------|-----|-------|---|------| +|Command queries |✓ |✓ |✓ |✓ | +|Queries from buffer| | |✓ |✓ | +|Toggle comments | | |✓ | | +|Prev/next answer | | |✓ | | +|Multiple answers | |✓ | | | +|Warnings as queries| | |✓ | | +|Session id | | |✓ | | + ### Vim * [cheat.sh-vim](https://github.com/dbeniamine/cheat.sh-vim) — Vim support diff --git a/lib/cheat_wrapper.py b/lib/cheat_wrapper.py index 60e5a81..6f89b66 100644 --- a/lib/cheat_wrapper.py +++ b/lib/cheat_wrapper.py @@ -21,7 +21,7 @@ MYDIR = os.path.abspath(os.path.join(__file__, '..', '..')) sys.path.append("%s/lib/" % MYDIR) from globals import error, ANSI2HTML, COLOR_STYLES from buttons import TWITTER_BUTTON, GITHUB_BUTTON, GITHUB_BUTTON_FOOTER -from languages_data import LEXER, LANGUAGE_ALIAS +from languages_data import LEXER, get_lexer_name from get_answer import get_topic_type, get_topics_list, get_answer, find_answer_by_keyword from beautifier import code_blocks # import beautifier @@ -94,7 +94,7 @@ def _colorize_ansi_answer(topic, answer, color_style, # pylint: di lexer_class = LEXER['bash'] if '/' in topic: section_name = topic.split('/', 1)[0].lower() - section_name = LANGUAGE_ALIAS.get(section_name, section_name) + section_name = get_lexer_name(section_name) lexer_class = LEXER.get(section_name, lexer_class) if section_name == 'php': answer = "\n" % answer diff --git a/lib/colorize_internal.py b/lib/colorize_internal.py index 746efc9..2d709ac 100644 --- a/lib/colorize_internal.py +++ b/lib/colorize_internal.py @@ -26,46 +26,53 @@ PALETTES = { }, } -PALETTES_REVERSE = { - 0: { - 1: Back.WHITE + Fore.BLACK, - 2: Style.DIM, - }, - 1: { - 1: Back.CYAN + Fore.BLACK, - 2: Style.DIM, - }, - 2: { - 1: Back.RED + Fore.BLACK, - 2: Style.DIM, - }, -} +def _reverse_palette(code): + return { + 1 : Fore.BLACK + _back_color(code), + 2 : Style.DIM + } + +def _back_color(code): + if code == 0 or (isinstance(code, str) and code.lower() == "white"): + return Back.WHITE + if code == 1 or (isinstance(code, str) and code.lower() == "cyan"): + return Back.CYAN + if code == 2 or (isinstance(code, str) and code.lower() == "red"): + return Back.RED + + return Back.WHITE + def colorize_internal(text, palette_number=1): """ Colorize `text`, use `palette` """ palette = PALETTES[palette_number] - palette_reverse = PALETTES_REVERSE[palette_number] - - def _colorize_curlies_block(text): - + palette_reverse = _reverse_palette(palette_number) + def _process_text(text): text = text.group()[1:-1] factor = 1 if text.startswith('-'): text = text[1:] factor = -1 stripped = text.lstrip('0123456789') - color_number = int(text[:len(text)-len(stripped)])*factor + return (text, stripped, factor) + + def _extract_color_number(text, stripped, factor=1): + return int(text[:len(text)-len(stripped)])*factor + + def _colorize_curlies_block(text): + text, stripped, factor = _process_text(text) + color_number = _extract_color_number(text, stripped, factor) + if stripped.startswith('='): stripped = stripped[1:] - reverse = False - if color_number < 0: + reverse = (color_number < 0) + if reverse: color_number = -color_number - reverse = True if reverse: stripped = palette_reverse[color_number] + stripped + Style.RESET_ALL diff --git a/lib/get_answer.py b/lib/get_answer.py index aac6fb8..4424cdc 100644 --- a/lib/get_answer.py +++ b/lib/get_answer.py @@ -27,7 +27,7 @@ import time import beautifier from globals import MYDIR, PATH_TLDR_PAGES, PATH_CHEAT_PAGES, PATH_CHEAT_SHEETS, COLOR_STYLES, REDISHOST from adapter_learnxiny import get_learnxiny, get_learnxiny_list, is_valid_learnxy -from languages_data import LANGUAGE_ALIAS, SO_NAME +from languages_data import LANGUAGE_ALIAS, SO_NAME, rewrite_editor_section_name from colorize_internal import colorize_internal # pylint: enable=wrong-import-position,wrong-import-order @@ -37,6 +37,7 @@ MAX_SEARCH_LEN = 20 INTERNAL_TOPICS = [ ':cht.sh', + ':cht.sh-posix', ':bash_completion', ':emacs', ':emacs-ivy', @@ -431,8 +432,10 @@ def get_answer(topic, keyword, options="", request_options=None): # pylint: disa return query section_name, rest = query.split('/', 1) + if ':' in section_name: + section_name = rewrite_editor_section_name(section_name) + section_name = SO_NAME.get(section_name, section_name) - print("%s/%s" % (section_name, rest)) return "%s/%s" % (section_name, rest) diff --git a/lib/languages_data.py b/lib/languages_data.py index 5c60e86..16f6c47 100644 --- a/lib/languages_data.py +++ b/lib/languages_data.py @@ -122,3 +122,72 @@ SO_NAME = { 'vb' : 'vba', 'mathematica': 'wolfram-mathematica', } + + +# +# conversion of internal programmin language names +# into canonical cheat.sh names +# + +ATOM_FT_NAME = { +} + +EMACS_FT_NAME = { +} + +SUBLIME_FT_NAME = { +} + +VIM_FT_NAME = { + 'asm': 'assembler', + 'javascript': 'js', +} + +VSCODE_FT_NAME = { +} + +def rewrite_editor_section_name(section_name): + """ + section name cen be specified in form "editor:editor-filetype" + and it will be rewritten into form "filetype" + basing on the editor filetypes names data. + If editor name is unknown, it is just cut off: notepad:js => js + + Known editors: + * atom + * vim + * emacs + * sublime + * vscode + + >>> rewrite_editor_section_name('js') + 'js' + >>> rewrite_editor_section_name('vscode:js') + 'js' + """ + if ':' not in section_name: + return section_name + + editor_name, section_name = section_name.split(':', 1) + editor_name_mapping = { + 'atom': ATOM_FT_NAME, + 'emacs': EMACS_FT_NAME, + 'sublime': SUBLIME_FT_NAME, + 'vim': VIM_FT_NAME, + 'vscode': VSCODE_FT_NAME, + } + if editor_name not in editor_name_mapping: + return section_name + return editor_name_mapping[editor_name].get(section_name, section_name) + +def get_lexer_name(section_name): + """ + Rewrite `section_name` for the further lexer search (for syntax highlighting) + """ + if ':' in section_name: + section_name = rewrite_editor_section_name(section_name) + return LANGUAGE_ALIAS.get(section_name, section_name) + +if __name__ == "__main__": + import doctest + doctest.testmod() diff --git a/lib/panela/panela_colors.py b/lib/panela/panela_colors.py index ad5cd76..00bf58b 100644 --- a/lib/panela/panela_colors.py +++ b/lib/panela/panela_colors.py @@ -1,5 +1,6 @@ # vim: encoding=utf-8 +import os import sys import colored import itertools @@ -633,7 +634,7 @@ class Template(object): def main(): "Only for experiments" - pagepath = os.join.path(MYDIR, "share/firstpage-v2.pnl") + pagepath = os.path.join(MYDIR, "share/firstpage-v2.pnl") template = Template() template.read(pagepath) template.apply_mask() diff --git a/share/cht.sh-posix.txt b/share/cht.sh-posix.txt new file mode 100755 index 0000000..86afd70 --- /dev/null +++ b/share/cht.sh-posix.txt @@ -0,0 +1,428 @@ +#!/bin/sh +# +# [X] open section +# [X] one shot mode +# [X] usage info +# [X] dependencies check +# [X] help +# [X] yank/y/copy/c +# [X] Y/C +# [X] eof problem +# [X] more +# [X] stealth mode +# +# here are several examples for the stealth mode: +# +# zip lists +# list permutation +# random list element +# reverse a list +# read json from file +# append string to a file +# run process in background +# count words in text counter +# group elements list + +__CHTSH_VERSION=4 +__CHTSH_DATETIME="2018-07-08 22:26:46 +0200" + +export LESSSECURE=1 +STEALTH_MAX_SELECTION_LENGTH=5 + +case "$OSTYPE" in + darwin*) is_macos=yes ;; + *) is_macos=no ;; +esac + +# for KSH93 +if ! local foo 2>/dev/null; then + alias local=typeset +fi + +get_query_options() +{ + local query="$*" + if [ -n "$CHTSH_QUERY_OPTIONS" ]; then + case $query in + *\?*) query="$query&${CHTSH_QUERY_OPTIONS}";; + *) query="$query?${CHTSH_QUERY_OPTIONS}";; + esac + fi + printf "%s" "$query" +} + +do_query() +{ + local query="$*" + local b_opts= + local uri="https://cht.sh/\"\$(get_query_options $query)\"" + + if [ -e "$HOME/.cht.sh/id" ]; then + b_opts="-b \"\$HOME/.cht.sh/id\"" + fi + + eval curl $b_opts -s $uri > "$TMP1" + + if [ -z "$lines" ] || [ "$(wc -l "$TMP1" | awk '{print $1}')" -lt "$lines" ]; then + cat "$TMP1" + else + ${PAGER:-$defpager} "$TMP1" + fi +} + +prepare_query() +{ + local section="$1"; shift + local input="$1"; shift + local arguments="$1" + + local query + if [ -z "$section" ] || [ x"${input}" != x"${input#/}" ]; then + query=$(printf %s "$input" | sed 's@ @/@; s@ @+@g') + else + query=$(printf %s "$section/$input" | sed 's@ @+@g') + fi + + [ -n "$arguments" ] && arguments="?$arguments" + printf %s "$query$arguments" +} + +get_list_of_sections() +{ + curl -s https://cht.sh/:list | grep -v '/.*/' | grep '/$' | xargs +} + +gen_random_str() +( + len=$1 + if command -v openssl >/dev/null; then + openssl rand -base64 $(($len*3/4)) | awk -v ORS='' // + else + rdev=/dev/urandom + for d in /dev/{srandom,random,arandom}; do + test -r $d && rdev=$d + done + if command -v hexdump >/dev/null; then + hexdump -vn $(($len/2)) -e '1/1 "%02X" 1 ""' $rdev + elif command -v xxd >/dev/null; then + xxd -l $(($len/2)) -ps $dev | awk -v ORS='' // + else + cd /tmp + s= + while [ $(echo "$s" | wc -c) -lt $len ]; do + s="$s$(mktemp -u XXXXXXXXXX)" + done + printf %.${len}s "$s" + fi + fi +) + +if [ -e "$HOME"/.cht.sh/cht.sh.conf ]; then + # shellcheck disable=SC1090,SC2002 + . "$HOME"/.cht.sh/cht.sh.conf +fi + +if [ "$1" = --read ]; then + read -r a || a=exit + printf "%s\n" "$a" + exit 0 +elif [ x"$1" = x--help ] || [ -z "$1" ]; then + cat </dev/null || echo 'DEPENDENCY: please install "xsel" for "copy"' >&2 +fi +command -v rlwrap >/dev/null || { echo 'DEPENDENCY: install "rlwrap" to use cht.sh in the shell mode' >&2; exit 1; } +command -v curl >/dev/null || { echo 'DEPENDENCY: install "curl" to use cht.sh' >&2; exit 1; } + +mkdir -p "$HOME/.cht.sh/" +lines=$(tput lines) + +if command -v less >/dev/null; then + defpager="less -R" +elif command -v more >/dev/null; then + defpager=more +else + defpager=cat +fi + +TMP1=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX) +trap 'rm -f $TMP1 $TMP2' EXIT +trap 'true' INT + +if ! [ -e "$HOME/.cht.sh/.hushlogin" ] && [ -z "$this_query" ]; then + echo "type 'help' for the cht.sh shell help" +fi + +while true; do + if [ "$section" != "" ]; then + full_prompt="$prompt/$section> " + else + full_prompt="$prompt> " + fi + + input=$( + rlwrap -H "$HOME/.cht.sh/history" -pgreen -C cht.sh -S "$full_prompt" sh "$0" --read | sed 's/ *#.*//' + ) + + case "$input" in + '?'|h|help) + cat < python zip list + cht.sh/python> zip list + cht.sh/go> /python zip list +EOF + continue + ;; + hush) + mkdir -p $HOME/.cht.sh/ && touch $HOME/.cht.sh/.hushlogin && echo "Initial 'use help' message was disabled" + continue + ;; + cd) + section="" + continue + ;; + "cd "*) + new_section=$(echo "$input" | sed 's/cd *//; s@/*$@@; s@^/*@@') + if [ -z "$new_section" ] || [ ".." = "$new_section" ]; then + section="" + else + valid_sections=$(get_list_of_sections) + valid=no; for q in $valid_sections; do [ "$q" = "$new_section/" ] && { valid=yes; break; }; done + if [ "$valid" = no ]; then + echo "Invalid section: $new_section" + echo "Valid sections:" + echo $valid_sections | xargs printf "%-10s\n" | tr ' ' . | xargs -n 10 | sed 's/\./ /g; s/^/ /' + continue + else + section="$new_section" + fi + fi + continue + ;; + exit|quit) + break + ;; + copy|yank|c|y) + if [ -z "$DISPLAY" ]; then + echo copy: supported only in the Desktop version + continue + fi + if [ -z "$input" ]; then + echo copy: Make at least one query first. + continue + else + curl -s https://cht.sh/"$(get_query_options "$query"?T)" > "$TMP1" + if [ "$is_macos" != yes ]; then + xsel -i < "$TMP1" + else + cat "$TMP1" | pbcopy + fi + echo "copy: $(wc -l "$TMP1" | awk '{print $1}') lines copied to the selection" + continue + fi + ;; + ccopy|cc|C|Y) + if [ -z "$DISPLAY" ]; then + echo copy: supported only in the Desktop version + continue + fi + if [ -z "$input" ]; then + echo copy: Make at least one query first. + continue + else + curl -s https://cht.sh/"$(get_query_options "$query"?TQ)" > "$TMP1" + if [ "$is_macos" != yes ]; then + xsel -i < "$TMP1" + else + cat "$TMP1" | pbcopy + fi + echo "copy: $(wc -l "$TMP1" | awk '{print $1}') lines copied to the selection" + continue + fi + ;; + id|"id "*) + id_file="$HOME/.cht.sh/id" + + if [ id = "$input" ]; then + new_id="" + else + new_id=$(echo "$input" | sed 's/id *//; s/ *$//; s/ /+/g') + fi + if [ "$new_id" = remove ]; then + if [ -e "$id_file" ]; then + rm -f -- "$id_file" && echo "id is removed" + else + echo "id was not set, so you can't remove it" + fi + continue + fi + if [ -n "$new_id" ] && [ reset != "$new_id" ] && [ $(/bin/echo -n "$new_id" | wc -c) -lt 16 ]; then + echo "ERROR: $new_id: Too short id. Minimal id length is 16. Use 'id reset' for a random id" + continue + fi + if [ -z "$new_id" ]; then + # if new_id is not specified check if we have some id already + # if yes, just show it + # if not, generate a new id + if [ -e "$id_file" ]; then + echo $(awk '$6 == "id" {print $NF}' <"$id_file" | tail -n 1) + continue + else + new_id=reset + fi + fi + if [ "$new_id" = reset ]; then + new_id=$(gen_random_str 12) + else + echo WARNING: if someone gueses your id, he can read your cht.sh search history + fi + if [ -e "$id_file" ] && grep -q '\tid\t[^\t][^\t]*$' "$id_file" 2> /dev/null; then + sed -i 's/\tid\t[^\t][^\t]*$/ id '"$new_id"'/' "$id_file" + else + if ! [ -e "$id_file" ]; then + printf '#\n\n' > "$id_file" + fi + printf ".cht.sh\tTRUE\t/\tTRUE\t0\tid\t$new_id\n" >> "$id_file" + fi + echo "$new_id" + continue + ;; + stealth|"stealth "*) + if [ "$input" != stealth ]; then + arguments=$(echo "$input" | sed 's/stealth //; s/ /\&/') + fi + trap break SIGINT + if [ "$is_macos" == yes ]; then + past=$(pbpaste) + else + past=$(xsel -o) + fi + printf "\033[0;31mstealth:\033[0m you are in the stealth mode; select any text in any window for a query\n" + printf "\033[0;31mstealth:\033[0m selections longer than $STEALTH_MAX_SELECTION_LENGTH words are ignored\n" + if [ -n "$arguments" ]; then + printf "\033[0;31mstealth:\033[0m query arguments: ?$arguments\n" + fi + printf "\033[0;31mstealth:\033[0m use ^C to leave this mode\n" + while true; do + if [ $is_macos == yes ]; then + current=$(pbpaste) + else + current=$(xsel -o) + fi + if [ "$past" != "$current" ]; then + past=$current + current_text="$(echo $current | tr -c '[a-zA-Z0-9]' ' ')" + if [ $(echo $current_text | wc -w) -gt "$STEALTH_MAX_SELECTION_LENGTH" ]; then + echo "\033[0;31mstealth:\033[0m selection length is longer than $STEALTH_MAX_SELECTION_LENGTH words; ignoring" + continue + else + printf "\n\033[0;31mstealth: \033[7m $current_text\033[0m\n" + query=$(prepare_query "$section" "$current_text" "$arguments") + do_query "$query" + fi + fi + sleep 1; + done + trap - SIGINT + continue + ;; + update) + [ -w "$0" ] || { echo "The script is readonly; please update manually: curl -s https://cht.sh/:bash | sudo tee $0"; continue; } + TMP2=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX) + curl -s https://cht.sh/:cht.sh > "$TMP2" + if ! cmp "$0" "$TMP2" > /dev/null 2>&1; then + if grep -q ^__CHTSH_VERSION= "$TMP2"; then + # section was vaildated by us already + args="--shell $section" + cp "$TMP2" "$0" && echo "Updated. Restarting..." && rm "$TMP2" && CHEATSH_RESTART=1 exec "$0" $args + else + echo "Something went wrong. Please update manually" + fi + else + echo "cht.sh is up to date. No update needed" + fi + rm -f "$TMP2" > /dev/null 2>&1 + continue + ;; + version) + insttime=$(ls -l -- "$0" | sed 's/ */ /g' | cut -d ' ' -f 6-8) + echo "cht.sh version $__CHTSH_VERSION of $__CHTSH_DATETIME; installed at: $insttime" + TMP2=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX) + if curl -s https://cht.sh/:cht.sh > "$TMP2"; then + if ! cmp "$0" "$TMP2" > /dev/null 2>&1; then + echo "Update needed (type 'update' for that)". + else + echo "Up to date. No update needed" + fi + fi + rm -f "$TMP2" > /dev/null 2>&1 + continue + ;; + "") + continue + ;; + esac + + query=$(prepare_query "$section" "$input") + do_query "$query" +done diff --git a/share/intro.txt b/share/intro.txt index cc8a9bf..7138588 100644 --- a/share/intro.txt +++ b/share/intro.txt @@ -163,7 +163,7 @@ can use TAB completion when writing its queries in {1bash} Install the TAB completion script for that. Assuming you use bash, you have to do: - {1mkdir -p ~/.bash.d/cht.sh} + {1mkdir -p ~/.bash.d/} {1curl} {2https://cht.sh/:bash_completion} {1> ~/.bash.d/cht.sh} {1echo 'source ~/.bash.d/cht.sh' >> ~/.bashrc} {1source ~/.bash.d/cht.sh} diff --git a/tests/results/0 b/tests/results/0 new file mode 100644 index 0000000..824872d --- /dev/null +++ b/tests/results/0 @@ -0,0 +1,16 @@ +1line +doc +func +hello +lambda +loops +recursion +Primitive_Datatypes_and_Operators +Variables_and_Collections +Control_Flow +Functions +Classes +Modules +Advanced +Comments +:learn diff --git a/tests/results/1 b/tests/results/1 new file mode 100644 index 0000000..7b1f52f --- /dev/null +++ b/tests/results/1 @@ -0,0 +1,17 @@ +# Displays everything in the target directory +ls path/to/the/target/directory + +# Displays everything including hidden files +ls -a + +# Displays all files, along with the size (with unit suffixes) and timestamp +ls -lh  + +# Display files, sorted by size +ls -S + +# Display directories only +ls -d */ + +# Display directories only, include hidden +ls -d .*/ */ diff --git a/tests/results/10 b/tests/results/10 new file mode 100644 index 0000000..d0db3d4 --- /dev/null +++ b/tests/results/10 @@ -0,0 +1,3 @@ +from shutil import copyfile + +copyfile(src, dst) diff --git a/tests/results/11 b/tests/results/11 new file mode 100644 index 0000000..7c53265 --- /dev/null +++ b/tests/results/11 @@ -0,0 +1,3 @@ +from shutil import copyfile + +copyfile(src, dst) diff --git a/tests/results/12 b/tests/results/12 new file mode 100644 index 0000000..8794df4 --- /dev/null +++ b/tests/results/12 @@ -0,0 +1,32 @@ + _ _ _ __    + ___| |__ ___ __ _| |_ ___| |__ \ \      The only cheat sheet you need    + / __| '_ \ / _ \/ _` | __| / __| '_ \ \ \  Unified access to the best     +| (__| | | | __/ (_| | |_ _\__ \ | | |/ /  community driven documentation + \___|_| |_|\___|\__,_|\__(_)___/_| |_/_/   repositories of the world      + ++------------------------+ +------------------------+ +------------------------+ +| $ curl cheat.sh/ls     | | $ cht.sh btrfs         | | $ cht.sh lua/:learn | +| $ curl cht.sh/btrfs    | | $ cht.sh tar~list      | | Learn any* programming | +| $ curl cht.sh/tar~list | | | | language not leaving | +| $ curl https://cht.sh  | | | | your shell | +| | | | | *) any of 60 | +| | | | | | ++-- queries with curl ---+ +- own optional client --+ +- learn, learn, learn! -+ ++------------------------+ +------------------------+ +------------------------+ +| $ cht.sh go/f<tab><tab>| | $ cht.sh --shell | | $ cht.sh go zip lists | +| go/for go/func | | cht.sh> help | | Ask any question using | +| $ cht.sh go/for | | ... | | cht.sh or curl cht.sh: | +| ... | | | | /go/zip+lists | +| | | | | (use /,+ when curling) | +| | | | | | ++---- TAB-completion ----+ +-- interactive shell ---+ +- programming questions-+ ++------------------------+ +------------------------+ +------------------------+ +| $ curl cht.sh/:help | | $ vim prg.py | | $ time curl cht.sh/ | +| see /:help and /:intro | | ... | | ... | +| for usage information | | zip lists _ | | real 0m0.075s | +| and README.md on GitHub| | <leader>KK | | | +| for the details | | *awesome* | | | +| *start here*| | | | | ++--- self-documented ----+ +- queries from editor! -+ +---- instant answers ---+ + +[Follow @igor_chubin for updates][github.com/chubin/cheat.sh] diff --git a/tests/results/13 b/tests/results/13 new file mode 100644 index 0000000..8794df4 --- /dev/null +++ b/tests/results/13 @@ -0,0 +1,32 @@ + _ _ _ __    + ___| |__ ___ __ _| |_ ___| |__ \ \      The only cheat sheet you need    + / __| '_ \ / _ \/ _` | __| / __| '_ \ \ \  Unified access to the best     +| (__| | | | __/ (_| | |_ _\__ \ | | |/ /  community driven documentation + \___|_| |_|\___|\__,_|\__(_)___/_| |_/_/   repositories of the world      + ++------------------------+ +------------------------+ +------------------------+ +| $ curl cheat.sh/ls     | | $ cht.sh btrfs         | | $ cht.sh lua/:learn | +| $ curl cht.sh/btrfs    | | $ cht.sh tar~list      | | Learn any* programming | +| $ curl cht.sh/tar~list | | | | language not leaving | +| $ curl https://cht.sh  | | | | your shell | +| | | | | *) any of 60 | +| | | | | | ++-- queries with curl ---+ +- own optional client --+ +- learn, learn, learn! -+ ++------------------------+ +------------------------+ +------------------------+ +| $ cht.sh go/f<tab><tab>| | $ cht.sh --shell | | $ cht.sh go zip lists | +| go/for go/func | | cht.sh> help | | Ask any question using | +| $ cht.sh go/for | | ... | | cht.sh or curl cht.sh: | +| ... | | | | /go/zip+lists | +| | | | | (use /,+ when curling) | +| | | | | | ++---- TAB-completion ----+ +-- interactive shell ---+ +- programming questions-+ ++------------------------+ +------------------------+ +------------------------+ +| $ curl cht.sh/:help | | $ vim prg.py | | $ time curl cht.sh/ | +| see /:help and /:intro | | ... | | ... | +| for usage information | | zip lists _ | | real 0m0.075s | +| and README.md on GitHub| | <leader>KK | | | +| for the details | | *awesome* | | | +| *start here*| | | | | ++--- self-documented ----+ +- queries from editor! -+ +---- instant answers ---+ + +[Follow @igor_chubin for updates][github.com/chubin/cheat.sh] diff --git a/tests/results/2 b/tests/results/2 new file mode 100644 index 0000000..41a116a --- /dev/null +++ b/tests/results/2 @@ -0,0 +1,17 @@ +# Displays everything in the target directory +ls path/to/the/target/directory + +# Displays everything including hidden files +ls -a + +# Displays all files, along with the size (with unit suffixes) and timestamp +ls -lh + +# Display files, sorted by size +ls -S + +# Display directories only +ls -d */ + +# Display directories only, include hidden +ls -d .*/ */ diff --git a/tests/results/3 b/tests/results/3 new file mode 100644 index 0000000..10b9309 --- /dev/null +++ b/tests/results/3 @@ -0,0 +1,54 @@ +# Create a btrfs file system on /dev/sdb, /dev/sdc, and /dev/sdd +mkfs.btrfs /dev/sdb /dev/sdc /dev/sdd + +# btrfs with just one hard drive, metadata not redundant  +# (this is danegerous: if your metadata is lost, your data is lost as well) +mkfs.btrfs -m single /dev/sdb + +# data to be redundant and metadata to be non-redundant: +mkfs.btrfs -m raid0 -d raid1 /dev/sdb /dev/sdc /dev/sdd + +# both data and metadata to be redundan +mkfs.btrfs -d raid1 /dev/sdb /dev/sdc /dev/sdd + +# To get a list of all btrfs file systems +btrfs filesystem show + +# detailed df for a fileesystem (mounted in /mnt) +btrfs filesystem df /mnt + +# resize btrfs online (-2g decreases, +2g increases) +btrfs filesystem resize -2g /mnt + +# use maximum space +btrfs filesystem resize max /mnt + +# add new device to a filesystem +btrfs device add /dev/sdf /mnt + +# remove devices from a filesystem +btrfs device delete missing /mnt + +# create the subvolume /mnt/sv1 in the /mnt volume +btrfs subvolume create /mnt/sv1 + +# list subvolumes +btrfs subvolume list /mnt + +# mount subvolume without mounting the main filesystem +mount -o subvol=sv1 /dev/sdb /mnt + +# delete subvolume +btrfs subvolume delete /mnt/sv1 + +# taking snapshot of a subvolume +btrfs subvolume snapshot /mnt/sv1 /mnt/sv1_snapshot + +# taking snapshot of a file (copy file by reference) +cp --reflink /mnt/sv1/test1 /mnt/sv1/test3 + +# convert ext3/ext4 to btrfs +btrfs-convert /dev/sdb1 + +# convert btrfs to ext3/ext4 +btrfs-convert -r /dev/sdb1 diff --git a/tests/results/4 b/tests/results/4 new file mode 100644 index 0000000..317da29 --- /dev/null +++ b/tests/results/4 @@ -0,0 +1,3 @@ + btrfs  +# create the subvolume /mnt/sv1 in the /mnt volume +btrfs subvolume create /mnt/sv1 diff --git a/tests/results/5 b/tests/results/5 new file mode 100644 index 0000000..0b9624b --- /dev/null +++ b/tests/results/5 @@ -0,0 +1,216 @@ +## curl cht.sh + +To access a cheat sheet you can simply issue a plain HTTP or HTTPS request +specifying the topic name in the query URL: + + curl cheat.sh/tar + curl https://cheat.sh/tar + +You can use the full service name, cheat.sh, or the shorter variant, cht.sh. +They are equivalent: + + curl https://cht.sh/tar + curl https://cheat.sh/tar + +The preferred access protocol is HTTPS, and you should use it always when possible. + +Cheat sheets in the root namespaces cover UNIX/Linux commands. + +Cheat sheets covering programming languages are located in subsections: + + curl cht.sh/go/func + +All cheat sheets in a subsection can be listed using a special query :list : + + curl cht.sh/go/:list + +There are several other special queries. All of them are starting with a colon. +See /:help for the full list of the special queries. + + +## Search + +If a cheat sheet is too large, you can cut the needed part out using an +additional search parameter. In this case, only the paragraph that contains the +search term will be displayed: + + curl cht.sh/tar~extract + +If the name of the cheat sheet is omitted, and only the serch query is specified, +all cheat sheets in the namespace are scanned, and the found occurrencies +are displayed: + + curl cht.sh/~extract + + +## Options + +cheat.sh queries as well as search queries have many options. +They can be specified as a part of the query string in the URL, after ?. +Short single letter options could be written all jointly together, +and long options are separated with &. For example, to switch +syntax highlighting off the T switch is used: + + curl cht.sh/tar?T + +Full list of all available cheat.sh options as well as description of all modes +of operation can be found in /:help, + + curl cht.sh/:help + + +## cht.sh client + +Though it's perfectly possible to access cheat.sh using curl (or any other +HTTP client) alone, there is a special client, that has several advantages +comparing to plain curling: cht.sh. + +To install the client in ~/bin: + + curl https://cht.sh/:cht.sh > ~/bin/cht.sh + chmod +x ~/bin/cht.sh + +Queries look the same, but you can separate words in the query with spaces, +instead of + as when using curl, what looks more natural: + + cht.sh python zip lists + + +## cht.sh shell + +If you always issuing queries about the same programming language, it's can be +more convenient to run the client in the shell mode and specify the queries +context: + + $ cht.sh --shell python + cht.sh/python> zip lists + +Of course, you can start the shell without the context too: + + $ cht.sh --shell + cht.sh> python zip lists + cht.sh> go http query + cht.sh> js iterate list + +If you ue predominantly one language but sometime issuing queries about other, +you may prepend the query with /: + + cht.sh/python> zip lists + cht.sh/python> /go http query + cht.sh/python> /js iterate list + + +## :learn + +If you are just start learning a new programming language, and you have no +distinct queries for the moment, cheat.sh can be a good starting point too. As +you know, it exports cheat sheets from the best cheat sheet repositories, and +one of them is Learn X in Y, a repository of concise documentation devoted +to learning programming languages from scratch (and not only them). + +If you want start learning a new programming language, do (use less -R because +the output could be quite big): + + curl cht.sh/elixir/:learn | less -R + +Or simply :learn with cht.sh (you don't need less -R here, because +cht.sh starts pager if needed automatically): + + cht.sh/elixir> :learn + + +## Programming languages questions + +One of the most important features of cheat.sh is that you can ask it any +questions about programming languages and instantly get answers on them. You +can use both direct HTTP queries or the cht.sh client for that: + + curl cht.sh/python/reverse+list + + cht.sh/python> reverse list + +In the latter case you don't need + to separate the words in the query, you can +do it in a more natural way, with spaces. + +If context in the cht.sh shell is not specified, you have to write the +programming language name as the first word in the query: + + cht.sh> python reverse list + +But if you are using only one programming language and all queries are about +it, it's better to change the current context and + + +## Comments + +Text in the answers is syntactically formatted as comment in the correspondent +programming language + +When using cht.sh, you can copy the result of the last query into the selection +buffer (you may also call it "clibpoard") using C (or c, with text): + + cht.sh/python> reverse list + ... + cht.sh/python> C + 1 lines copied + + +## bash TAB-completion for cht.sh + +One of the advantages of the cht.sh client comparing to plain curl is that you +can use TAB completion when writing its queries in bash +(other supported shells: zsh and fish). + +Install the TAB completion script for that. Assuming you use bash, you have to do: + + mkdir -p ~/.bash.d/ + curl https://cht.sh/:bash_completion > ~/.bash.d/cht.sh + echo 'source ~/.bash.d/cht.sh' >> ~/.bashrc + source ~/.bash.d/cht.sh + + +## Editor + +You can access cheat.sh directly from editors: Vim and Emacs. +It's a very important feature! You should absolutely like it. + +Imagine: +instead of switching to your browser, googling, browsing Stack Overflow +and eventually copying the code snippets you need and later pasting them into +the editor, you can achieve the same instantly and without leaving +the editor at all! + +Here is how it looks like: + +1. In Vim, if you have a question while editing a program, you can just type +your question directly in the buffer and press KK. You will get +the answer to your question in pager. (with KB you'll get the answer +in a separate buffer). + +2. If you like the answer. You can manually paste it from the buffer or +the pager, or if you are lazy you can use KP to paste it under +your question (KR will replace your question). If you want the +answer without the comments, KC replays the last query +toggling them. + +You have to install cheat.sh Vim/Emacs plugins for the editor support. +See /:vim or /:emacs with the detailed installation instructions. + + +## Feature requests, feedback and contribution + +If you want to submit a new community driver repository for cheat.sh please +open a ticket on the project page on GitHub. + +If you want to modify an existing cheat sheet, please check the source of the +cheat sheet (it is always displayed in the cheat sheet bottom line). + +If you want to add a new cheat sheet, add it here: +https://github.com/chubin/cheat.sheets + +If you want to suggest a new feature for cheat.sh, or if you've found a bug, +please open a new issue on github: +https://github.com/chubin/cheat.sh + +If you want to get the major project updates, follow @igor_chubin in Twitter +or this RSS feed: https://twitrss.me/twitter_user_to_rss/?user=igor_chubin diff --git a/tests/results/6 b/tests/results/6 new file mode 100644 index 0000000..4072487 --- /dev/null +++ b/tests/results/6 @@ -0,0 +1,85 @@ +Usage: + + $ curl cheat.sh/TOPIC show cheat sheet on the TOPIC + $ curl cheat.sh/TOPIC/SUB show cheat sheet on the SUB topic in TOPIC + $ curl cheat.sh/~KEYWORD search cheat sheets for KEYWORD + +Options: + + ?OPTIONS + + q quiet mode, don't show github/twitter buttons + T text only, no ANSI sequences + style=STYLE color style + + c do not comment text, do not shift code (QUERY+ only) + C do not comment text, shift code (QUERY+ only) + Q code only, don't show text (QUERY+ only) + +Options can be combined together in this way: + + curl 'cheat.sh/for?qT&style=bw' + +(when using & in shell, don't forget to specify the quotes or escape & with \) + +Special pages: + + :help this page + :list list all cheat sheets + :post how to post new cheat sheet + :cht.sh shell client (cht.sh) + :bash_completion bash function for tab completion + :styles list of color styles + :styles-demo show color styles usage examples + +Shell client: + + $ curl https://cht.sh/:cht.sh > ~/bin/cht.sh + $ chmod +x ~/bin/cht.sh + $ cht.sh python :learn + $ cht.sh --shell + +Tab completion: + + $ mkdir -p ~/.bash.d/ + $ curl cheat.sh/:bash_completion > ~/.bash.d/cht.sh + $ . ~/.bash.d/cht.sh + $ echo '. ~/.bash.d/cht.sh' >> ~/.bashrc + +Editor integration: + + :emacs see the page for the Emacs configuration + :vim see the page for the Vim configuration + +Search: + + /~snapshot look for "snapshot" in the first level cheat sheets + /~ssh~passphrase several keywords can be combined together using ~ + /scala/~closure look for "closure" in scala cheat sheets + /~snapshot/r look for "snapshot" in all cheat sheets recursively + +You can use special search options after the closing slash: + + /~shot/bi case insensitive (i), word boundaries (b) + +List of search options: + + b word boundaries + i case insensitive search + r recursive + +Programming languages topics: + +each programming language topic has the following subptopics: + + hello hello world + how to start the program + :learn big cheat sheet for learning language from scratch + :list list of topics + +Support programming languages: + + go + scala + rust + python + php diff --git a/tests/results/7 b/tests/results/7 new file mode 100644 index 0000000..b1b99fe --- /dev/null +++ b/tests/results/7 @@ -0,0 +1,389 @@ +#!/usr/bin/env bash +# +# [X] open section +# [X] one shot mode +# [X] usage info +# [X] dependencies check +# [X] help +# [X] yank/y/copy/c +# [X] Y/C +# [X] eof problem +# [X] less +# [X] stealth mode +# +# here are several examples for the stealth mode: +# +# zip lists +# list permutation +# random list element +# reverse a list +# read json from file +# append string to a file +# run process in background +# count words in text counter +# group elements list + +__CHTSH_VERSION=4 +__CHTSH_DATETIME="2018-07-08 22:26:46 +0200" + +export LESSSECURE=1 +STEALTH_MAX_SELECTION_LENGTH=5 + +case "$OSTYPE" in + darwin*) is_macos=yes ;; + *) is_macos=no ;; +esac + +get_query_options() +{ + local query="$*" + if [ -n "$CHTSH_QUERY_OPTIONS" ]; then + if [[ $query == *\?* ]]; then + query="$query&${CHTSH_QUERY_OPTIONS}" + else + query="$query?${CHTSH_QUERY_OPTIONS}" + fi + fi + echo "$query" +} + +do_query() +{ + local query="$*" + local b_opts=() + + if [ -e "$HOME/.cht.sh/id" ]; then + b_opts=(-b "$HOME/.cht.sh/id") + fi + + curl "${b_opts[@]}" -s https://cht.sh/"$(get_query_options $query)" > "$TMP1" + + if [ -z "$lines" ] || [ "$(wc -l "$TMP1" | awk '{print $1}')" -lt "$lines" ]; then + cat "$TMP1" + else + less -R "$TMP1" + fi +} + +prepare_query() +{ + local section="$1"; shift + local input="$1"; shift + local arguments="$1"; shift + + local query + if [ -z "$section" ] || [[ "$input" = /* ]]; then + query=$(echo "$input" | sed 's@ @/@; s@ @+@g') + else + query=$(echo "$section/$input" | sed 's@ @+@g') + fi + + [ -n "$arguments" ] && arguments="?$arguments" + echo "$query$arguments" +} + +get_list_of_sections() +{ + curl -s https://cht.sh/:list | grep -v '/.*/' | grep '/$' +} + +if [ -e "$HOME"/.cht.sh/cht.sh.conf ]; then + # shellcheck disable=SC1090,SC2002 + source <( cat "$HOME"/.cht.sh/cht.sh.conf | sed 's/#.*//' | grep -xv '' | sed s/^/CHTSH_/ ) >& /dev/null +fi + +if [ "$1" == --read ]; then + read -r a || a=exit + echo $a + exit 0 +elif [ "$1" == --help ] || [ -z "$1" ]; then + cat <& /dev/null || { echo 'DEPENDENCY: please install "xsel" for "copy"' >&2; } +fi +which rlwrap >& /dev/null || { echo 'DEPENDENCY: install "rlwrap" to use cht.sh in the shell mode' >&2; exit 1; } +which curl >& /dev/null || { echo 'DEPENDENCY: install "curl" to use cht.sh' >&2; exit 1; } + +mkdir -p "$HOME/.cht.sh/" +lines=$(tput lines) + +TMP1=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX) +trap 'rm -f $TMP1 $TMP2' EXIT +trap 'true' INT + +if ! [ -e "$HOME/.cht.sh/.hushlogin" ] && [ -z "$this_query" ]; then + echo "type 'help' for the cht.sh shell help" +fi + +while true; do + if [ "$section" != "" ]; then + full_prompt="$prompt/$section> " + else + full_prompt="$prompt> " + fi + + input=$( + rlwrap -H $HOME/.cht.sh/history -pgreen -C cht.sh -S "$full_prompt" bash "$0" --read | sed 's/ *#.*//' + ) + + case "$input" in + '?'|h|help) + cat < python zip list + cht.sh/python> zip list + cht.sh/go> /python zip list +EOF + continue + ;; + hush) + mkdir -p $HOME/.cht.sh/ && touch $HOME/.cht.sh/.hushlogin && echo "Initial 'use help' message was disabled" + continue + ;; + cd) + section="" + continue + ;; + "cd "*) + new_section=$(echo "$input" | sed 's/cd //; s/ .*//; s@/\+$@@; s@^/\+@@') + if [ "$new_section" = "" ] || [ "$new_section" = ".." ] || [ "$new_section" = / ]; then + section="" + else + valid_sections=($(get_list_of_sections)) + valid=no; for q in "${valid_sections[@]}"; do [[ "$q" == $new_section/ ]] && { valid=yes; break; }; done + if [ "$valid" = no ]; then + echo "Invalid section: $new_section" + echo "Valid sections:" + echo "${valid_sections[@]}" | xargs printf "%-10s\n" | tr ' ' . | xargs -n 10 | sed 's/\./ /g; s/^/ /' + continue + else + section="$new_section" + fi + fi + continue + ;; + exit|quit) + break + ;; + copy|yank|c|y) + if [ -z "$DISPLAY" ]; then + echo copy: supported only in the Desktop version + continue + fi + if [ -z "$input" ]; then + echo copy: Make at least one query first. + continue + else + curl -s https://cht.sh/"$(get_query_options "$query"?T)" > "$TMP1" + if [ "$is_macos" != yes ]; then + xsel -i < "$TMP1" + else + cat "$TMP1" | pbcopy + fi + echo "copy: $(wc -l "$TMP1" | awk '{print $1}') lines copied to the selection" + continue + fi + ;; + ccopy|cc|C|Y) + if [ -z "$DISPLAY" ]; then + echo copy: supported only in the Desktop version + continue + fi + if [ -z "$input" ]; then + echo copy: Make at least one query first. + continue + else + curl -s https://cht.sh/"$(get_query_options "$query"?TQ)" > "$TMP1" + if [ "$is_macos" != yes ]; then + xsel -i < "$TMP1" + else + cat "$TMP1" | pbcopy + fi + echo "copy: $(wc -l "$TMP1" | awk '{print $1}') lines copied to the selection" + continue + fi + ;; + id|"id "*) + id_file="$HOME/.cht.sh/id" + + if [ "$input" = id ]; then + new_id="" + else + new_id=$(echo "$input" | sed 's/id \+//; s/ *$//; s/ /+/g') + fi + if [ "$new_id" = remove ]; then + if [ -e "$id_file" ]; then + rm -f "$id_file" && echo "id is removed" + else + echo "id was not set, so you can't remove it" + fi + continue + fi + if [ -n "$new_id" ] && [ "$new_id" != reset ] && [ "$(echo $new_id | wc -c)" -lt 16 ]; then + echo "ERROR: $new_id: Too short id. Minimal id length is 16. Use 'id reset' for a random id" + continue + fi + if [ -z "$new_id" ]; then + # if new_id is not specified check if we have some id already + # if yes, just show it + # if not, generate a new id + if [ -e "$id_file" ]; then + echo $(cat "$id_file" | awk '{if ($6 == "id") print $NF}' | head -1) + continue + else + new_id=reset + fi + fi + if [ "$new_id" = reset ]; then + new_id="$(cat /dev/urandom 2> /dev/null | env LC_CTYPE=C tr -cd 'a-f0-9' 2> /dev/null | head -c 32)" + else + echo WARNING: if someone gueses your id, he can read your cht.sh search history + fi + if [ -e "$id_file" ] && grep -q '\tid\t[^\t]\+$' "$id_file" 2> /dev/null; then + sed -i 's/\tid\t[^\t]\+$/ id '"$new_id"'/' "$id_file" + else + if ! [ -e "$id_file" ]; then + printf '#\n\n' > "$id_file" + fi + printf ".cht.sh\tTRUE\t/\tTRUE\t0\tid\t$new_id\n" >> "$id_file" + fi + echo "$new_id" + continue + ;; + stealth|"stealth "*) + if [ "$input" != stealth ]; then + arguments=$(echo "$input" | sed 's/stealth //; s/ /\&/') + fi + trap break SIGINT + if [ "$is_macos" == yes ]; then + past=$(pbpaste) + else + past=$(xsel -o) + fi + printf "\033[0;31mstealth:\033[0m you are in the stealth mode; select any text in any window for a query\n" + printf "\033[0;31mstealth:\033[0m selections longer than $STEALTH_MAX_SELECTION_LENGTH words are ignored\n" + if [ -n "$arguments" ]; then + printf "\033[0;31mstealth:\033[0m query arguments: ?$arguments\n" + fi + printf "\033[0;31mstealth:\033[0m use ^C to leave this mode\n" + while true; do + if [ $is_macos == yes ]; then + current=$(pbpaste) + else + current=$(xsel -o) + fi + if [ "$past" != "$current" ]; then + past=$current + current_text="$(echo $current | tr -c '[a-zA-Z0-9]' ' ')" + if [ $(echo $current_text | wc -w) -gt "$STEALTH_MAX_SELECTION_LENGTH" ]; then + echo "\033[0;31mstealth:\033[0m selection length is longer than $STEALTH_MAX_SELECTION_LENGTH words; ignoring" + continue + else + printf "\n\033[0;31mstealth: \033[7m $current_text\033[0m\n" + query=$(prepare_query "$section" "$current_text" "$arguments") + do_query "$query" + fi + fi + sleep 1; + done + trap - SIGINT + continue + ;; + update) + [ -w "$0" ] || { echo "The script is readonly; please update manually: curl -s https://cht.sh/:bash | sudo tee $0"; continue; } + TMP2=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX) + curl -s https://cht.sh/:cht.sh > "$TMP2" + if ! cmp "$0" "$TMP2" > /dev/null 2>&1; then + if grep -q ^__CHTSH_VERSION= "$TMP2"; then + args=(--shell) + [ -n "$section" ] && args=("${args[@]}" "$section") + cp "$TMP2" "$0" && echo "Updated. Restarting..." && rm "$TMP2" && CHEATSH_RESTART=1 exec "$0" "${args[@]}" + else + echo "Something went wrong. Please update manually" + fi + else + echo "cht.sh is up to date. No update needed" + fi + rm -f "$TMP2" > /dev/null 2>&1 + continue + ;; + version) + echo "cht.sh version $__CHTSH_VERSION of $__CHTSH_DATETIME; installed at: $(stat -c %y "$0" | sed 's@\..* @ @')" + TMP2=$(mktemp /tmp/cht.sh.XXXXXXXXXXXXX) + if curl -s https://cht.sh/:cht.sh > "$TMP2"; then + if ! cmp "$0" "$TMP2" > /dev/null 2>&1; then + echo "Update needed (type 'update' for that)". + else + echo "Up to date. No update needed" + fi + fi + rm -f "$TMP2" > /dev/null 2>&1 + continue + ;; + "") + continue + ;; + esac + + query=$(prepare_query "$section" "$input") + do_query "$query" +done diff --git a/tests/results/8 b/tests/results/8 new file mode 100644 index 0000000..b6ca4a7 --- /dev/null +++ b/tests/results/8 @@ -0,0 +1,16 @@ +# How do I copy a file in python? +#  +# shutil (http://docs.python.org/2/library/shutil.html) has many methods +# you can use. One of which is: + +from shutil import copyfile + +copyfile(src, dst) + +# Copy the contents of the file named src to a file named dst. The +# destination location must be writable; otherwise, an IOError exception +# will be raised. If dst already exists, it will be replaced. Special +# files such as character or block devices and pipes cannot be copied +# with this function. src and dst are path names given as strings. +#  +# [Swati] [so/q/123198] [cc by-sa 3.0] diff --git a/tests/results/9 b/tests/results/9 new file mode 100644 index 0000000..b6ca4a7 --- /dev/null +++ b/tests/results/9 @@ -0,0 +1,16 @@ +# How do I copy a file in python? +#  +# shutil (http://docs.python.org/2/library/shutil.html) has many methods +# you can use. One of which is: + +from shutil import copyfile + +copyfile(src, dst) + +# Copy the contents of the file named src to a file named dst. The +# destination location must be writable; otherwise, an IOError exception +# will be raised. If dst already exists, it will be replaced. Special +# files such as character or block devices and pipes cannot be copied +# with this function. src and dst are path names given as strings. +#  +# [Swati] [so/q/123198] [cc by-sa 3.0] diff --git a/tests/run-tests.sh b/tests/run-tests.sh new file mode 100644 index 0000000..3ce9701 --- /dev/null +++ b/tests/run-tests.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +TMP=$(mktemp /tmp/cht.sh.tests-XXXXXXXXXXXXXX) +TMP2=$(mktemp /tmp/cht.sh.tests-XXXXXXXXXXXXXX) +trap 'rm -rf $TMP $TMP2' EXIT + + +i=0 +failed=0 +while read -r test_line; do + eval "$test_line" > "$TMP" + diff results/"$i" "$TMP" > "$TMP2" + if [ "$?" != 0 ]; then + echo FAILED: [$i] $test_line + ((failed++)) + fi + ((i++)) +done < tests.txt + +echo TESTS/OK/FAILED "$i/$[i-failed]/$failed" + + diff --git a/tests/tests.txt b/tests/tests.txt new file mode 100644 index 0000000..5187919 --- /dev/null +++ b/tests/tests.txt @@ -0,0 +1,14 @@ +cht.sh python :list +cht.sh ls +cht.sh ls?T +cht.sh btrfs +cht.sh btrfs~volume +cht.sh :intro +cht.sh :help +cht.sh :cht.sh +cht.sh python copy file +cht.sh python/copy+file +cht.sh python/copy+file?Q +cht.sh python/copy+file?QT +cht.sh / +cht.sh //