Compare commits

...

21 Commits
1.2 ... master

Author SHA1 Message Date
Rafal Paluch 846349613f poprawka flash aby dzialala punktacja 2025-12-10 20:28:16 +01:00
pali112 942a39114f Update README.md 2025-12-09 13:25:26 -08:00
Juan Enrique 37f609eaeb
Update flash (#48)
Minor typo
2023-11-06 11:33:36 -08:00
Shubham Swapneel Shah 47a635a645
Updated Readme file (#43)
Co-authored-by: Bryan Jenks <bryanjenks@protonmail.com>
2021-10-11 01:17:34 -07:00
Sami Kankaristo 8915b54e22
Remove unnecessary `cd` commands; Output errors to stderr (#40)
As discussed in a YouTube comment (https://www.youtube.com/watch?v=KEWhOzDCfLg&lc=UgzqmZf7hgBRjGLe-Pp4AaABAg), the `cd` commands to "return" back to the original directory are unnecessary, because it is *impossible* for a script to change the working directory of a shell.

When you run a `cd` command in a script, the working directory does change, but only for the script. When the script exits, nothing has happened to the working directory of the shell where you ran the script.

In fact, it is *impossible* for a script to change the working directory of the shell, even if you wanted to do that. Some ways you can change the working directory:
- an alias that runs a `cd` command (an alias is equivalent to running the commands in your shell)
    - `alias gohome="cd ~"
- a shell function that runs a `cd` command (this is the primary reason why things like z.lua are implemented as a shell function, not a script)
    - `function gohome() { cd ~ }`
- sourcing a script (so there is a way to do it with a script, but you have to run the script in a specific way, and this will also make exit quit the shell, not just the script)
    - `source ./script-name`

These are the ways I know of doing it, there may be some others.

Even if a script could change the shell's working directory, `fla.sh` is doing `cd "$PWD"`, which is basically a no-op, because `$PWD` is automatically updated:
```bash
echo "$PWD"

# go to the flashcard decks directory
cd "$DIR"

echo "$PWD"
```

The above outputs:
```
/home/sami
/home/sami/.local/share/flash
```

So, doing `cd $PWD` actually would not return back to the original directory, it would stay in whatever directory you've cd'd into.

-----

Another minor change in this PR is to output errors to stderr instead of stdout (before this change, errors were output to stdout).

With `fla.sh`, this doesn't really make much of a difference, but generally you want to output errors to stderr. This is useful, if you want to run a script quietly, but still want to see errors. If errors are output to stderr, this can be done with by running e.g.:
```bash
./script-name > /dev/null
```

The above will hide all regular output (redirecting stdout to `/dev/null`), but will still show anything output to stderr (i.e. error messages). To also hide error messages (make a script run completely silently), you can run:
```bash
./script-name > /dev/null 2>&1
```

The above `2>&1` syntax redirects stderr (`2>`) to the same place where stdout is redirected, and `> /dev/null` is redirecting stdout to `/dev/null`.

To only hide error messages, but show regular output, you could run `./script-name 2> /dev/null`, but that might not be a smart thing to do (if there are errors, you probably want to know about them).

The proposed change uses `>&2`, which redirects stdout to stderr, so that regular print commands (e.g. `echo`) are displayed on stderr. Both stdout and stderr are shown similarly in a terminal, but they're still separate, so they can be redirected, etc. Some terminals may also show stderr messages differently.

Both `echo "..." >&2` and `>&2 echo "..."` work identically, but I've used `>&2 echo "..."` because I think it's more intentional ("the following output is an error"), and if there's a long error message, the `>&2` could get "lost" at the end of a line. I picked it up on Stack Overflow, and I've used it ever since:
https://stackoverflow.com/a/23550347
2021-01-24 14:52:57 -08:00
Bryan Jenks f5ebff2e15
update version? 2021-01-24 14:23:08 -08:00
bryan 960f0b4316 bye bye travis 2020-12-12 23:27:35 -08:00
Bryan Jenks a16bd4393c
try this one? 2020-12-12 23:22:36 -08:00
Bryan Jenks d98f6a4a0b
fix name 2020-12-12 23:19:47 -08:00
Bryan Jenks 3876b727d5
add shell check gh action 2020-12-12 23:19:26 -08:00
Bryan Jenks 7b5b838965
add GH sponsors 2020-12-09 09:23:13 -08:00
bryan 58763294be Merge branch 'master' of https://github.com/tallguyjenks/fla.sh into master 2020-12-06 18:53:33 -08:00
bryan 8876db2694 --number to -b for portability solves #39 2020-12-06 18:53:10 -08:00
Bryan Jenks bf17b7d3c0
Version update in the command 2020-10-16 09:43:03 -07:00
Bryan Jenks 3ea4c26568
test workflows 2020-09-29 21:34:44 -07:00
Bryan Jenks 5ebdfbe263
test stale workflow 2020-09-29 21:31:08 -07:00
Bryan Jenks eeb7ed900a
smart phone verbiage 2020-09-29 14:55:47 -07:00
Bryan Jenks c6e14ac11e
fix weird commit 2020-09-17 11:14:22 -07:00
bryan 032ed7b627 Auto stash before merge of "master" and "origin/master" 2020-08-16 00:43:28 -07:00
eriteric 1f9a0ea7c8
provided extension for sed backups (#35)
* provided extension for sed backups

* Use ./*glob* in rm so names with dashes won't become options
2020-08-09 21:15:06 -07:00
anntnzrb 55b8b9a896
shfmt formatting & if-else shortened (minor) (#33)
* Applied shfmt formatting

* Minor optimizations

Some if-else flows only contained 1 statement, in shell, a shorter
version of those can be achieved by using the conditional operators,
among other tiny edits.

* Extra safety for multiple conditions

This is probably unnecessary, but just for extra safety, braces can be
added.
2020-08-05 22:42:58 -07:00
8 changed files with 159 additions and 124 deletions

2
.github/FUNDING.yml vendored
View File

@ -1,5 +1,5 @@
# These are supported funding model platforms # These are supported funding model platforms
patreon: bryanjenks patreon: bryanjenks
github: tallguyjenks
custom: ["https://www.buymeacoffee.com/tallguyjenks", "https://www.paypal.me/tallguyjenks"] custom: ["https://www.buymeacoffee.com/tallguyjenks", "https://www.paypal.me/tallguyjenks"]

View File

@ -28,6 +28,13 @@ If applicable, add screenshots to help explain your problem.
- Terminal Emulator [e.g. st, kitty, etc] - Terminal Emulator [e.g. st, kitty, etc]
- Shell [e.g. bash, zsh, fish] - Shell [e.g. bash, zsh, fish]
## Smartphone (please complete the following information):
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.

13
.github/workflows/greetings.yml vendored Normal file
View File

@ -0,0 +1,13 @@
name: Greetings
on: [pull_request, issues]
jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'This was your first issue! Thank you for contributing!'' first issue'
pr-message: 'This was your first Pull Request! Thank you for contributing!'' first pr'

17
.github/workflows/shellcheck.yml vendored Normal file
View File

@ -0,0 +1,17 @@
# from here: https://github.com/marketplace/actions/shellcheck
on:
push:
branch:
- master
name: 'Trigger: Push action'
jobs:
shellcheck:
name: Shellcheck
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: ShellCheck
uses: ludeeus/action-shellcheck@1.0.0

19
.github/workflows/stale.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: Mark stale issues and pull requests
on:
schedule:
- cron: "30 1 * * *"
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: 'Stale issue message'
stale-pr-message: 'Stale pull request message'
stale-issue-label: 'no-issue-activity'
stale-pr-label: 'no-pr-activity'

View File

@ -1,3 +0,0 @@
script:
# Fail if any of these files have warnings
- shellcheck -s bash flash

View File

@ -1,19 +1,15 @@
<!-- Header & Preview Image -->
<h1 align="center">
<img src="/img/flashheader.png" height="50%" width="50%">
</h1>
<!-- Shields --> <!-- Shields -->
<p align="center"> <p align="center">
<a href="https://github.com/tallguyjenks/fla.sh/blob/master/LICENSE"><img src="https://img.shields.io/static/v1.svg?style=flat&label=License&message=MIT&logoColor=eceff4&logo=github&colorA=black&colorB=green"/></a> <a href="https://github.com/tallguyjenks/fla.sh/blob/master/LICENSE"><img src="https://img.shields.io/static/v1.svg?style=flat&label=License&message=MIT&logoColor=eceff4&logo=github&colorA=black&colorB=green"/></a>
<a href="https://img.shields.io/travis/tallguyjenks/fla.sh/master"><img src="https://img.shields.io/travis/tallguyjenks/fla.sh/master"></a>
<img src="https://img.shields.io/github/commit-activity/m/tallguyjenks/fla.sh"> <img src="https://img.shields.io/github/commit-activity/m/tallguyjenks/fla.sh">
<a href="https://github.com/tallguyjenks/fla.sh/graphs/contributors"><img src="https://img.shields.io/github/contributors/tallguyjenks/fla.sh"></a> <a href="https://github.com/tallguyjenks/fla.sh/graphs/contributors"><img src="https://img.shields.io/github/contributors/tallguyjenks/fla.sh"></a>
<img src="https://img.shields.io/github/v/release/tallguyjenks/fla.sh"> <img src="https://img.shields.io/github/v/release/tallguyjenks/fla.sh">
</p> </p>
<!-- Description --> <!-- Description -->
> flashcards in your terminal! This script was inspired by a basic script i saw in a youtube video by a user named nixcasts. I Like the Anki flashcard system and so im working to replicate it in a simple manner using plain text documents and a shell script to aid my ability to study with active recall and spaced repetition. > Flashcards in your terminal!
>
> This script was inspired by a basic script that I had seen in a youtube video by a user named nixcasts. I like the Anki flashcard system, hence I'm working to replicate it in a simple manner using plain text documents and a shell script to aid my ability to study with active recall and spaced repetition.
![Preview of fla.sh](./img/flash_preview.png) ![Preview of fla.sh](./img/flash_preview.png)
@ -43,7 +39,7 @@ Untested, not sure if this script and its dependencies will work with WSL or not
Will need to have `brew` to install dependencies listed below and also `brew install coreutils` to get the GNU core utilities as `shuf` is not in macOS by default. Will need to have `brew` to install dependencies listed below and also `brew install coreutils` to get the GNU core utilities as `shuf` is not in macOS by default.
You will need to put the script itself somewhere in your `$PATH` and execute it to initialize setup. You will need to put the script itself somewhere in your `$PATH` and execute it to initialize the setup.
Confirmed to work on macOS 10.14.6 more recent version welcome to test and file an issue/pull request to update README if other versions run the script as it should. Confirmed to work on macOS 10.14.6 more recent version welcome to test and file an issue/pull request to update README if other versions run the script as it should.
@ -77,11 +73,11 @@ Organized like this:
**Fourth Field:** _The Score*_ **Fourth Field:** _The Score*_
> \* The score determines how often which cards are shown to you. A good idea is to start all your cards out at 0 so they are all served to you equally. As you study and review and mark the more familiar cards as 'Mild' or 'Easy' more points will be added. The lower point cards are sorted to the top and the top 10 are taken and shuffled and then drawn from. This way as you learn the material the items you are less familiar with bubble up into the shuffled pool for drawing and those that go up in points due to increased familiarity go down because you're rating the material as easier. > \* The score determines how often and which cards are shown to you. A good idea is to start all your cards out at 0 so that all are served to you equally. As you study, review, and mark the more familiar cards as 'Mild' or 'Easy', more points will be added. The lower point cards are sorted to the top and the top 10 are taken, shuffled, and then drawn from. This way as you learn the material and the items you are less familiar with bubble up into the shuffled pool for drawing and those that go up in points due to increased familiarity go down because you're rating the material as easier.
### Decks ### Decks
If you would like to browse a collection of decks readily available in your subject matter that are comaptible with [fla.sh](https://github.com/tallguyjenks/fla.sh) then you should check out [Flash Decks](https://github.com/tallguyjenks/Flash-Decks). If you would like to browse through a collection of decks readily available in your subject matter that are comaptible with [fla.sh](https://github.com/tallguyjenks/fla.sh) then you should check out [Flash Decks](https://github.com/tallguyjenks/Flash-Decks).
## Media (accepting contributions) ## Media (accepting contributions)

206
flash
View File

@ -24,48 +24,48 @@
#==============================================================# #==============================================================#
# USER CUSTOMIZABLE VARIABLES # USER CUSTOMIZABLE VARIABLES
CARD_POOL_SIZE=10 ######## How large the pool size is for shuf to draw from CARD_POOL_SIZE=10 ######## How large the pool size is for shuf to draw from
SEARCH_DEPTH=999 ######### How many levels to recursively search for .csv's in .local/share/flash SEARCH_DEPTH=999 ######### How many levels to recursively search for .csv's in .local/share/flash
PREVIEWER='bat' ########## What fzf previewer to use when searching through decks PREVIEWER='bat' ########## What fzf previewer to use when searching through decks
CURR_DECK_DISPLAY="file" # Options are 'file' or 'path' CURR_DECK_DISPLAY="file" # Options are 'file' or 'path'
# ANSI FOREGROUND ESCAPE COLORS # ANSI FOREGROUND ESCAPE COLORS
RED='\033[0;31m' RED='\033[0;31m'
LRED='\033[1;31m' LRED='\033[1;31m'
YELLOW='\033[1;33m' YELLOW='\033[1;33m'
GREEN='\033[0;32m' GREEN='\033[0;32m'
LGREEN='\033[1;32m' LGREEN='\033[1;32m'
LBLUE='\033[1;34m' LBLUE='\033[1;34m'
CYAN='\033[0;36m' CYAN='\033[0;36m'
LCYAN='\033[1;36m' LCYAN='\033[1;36m'
ORANGE='\033[0;33m' ORANGE='\033[0;33m'
LGREY='\033[0;37m' LGREY='\033[0;37m'
WHITE='\033[1;37m' WHITE='\033[1;37m'
NC='\033[0m' # No Color NC='\033[0m' # No Color
# ANSI BACKGROUND ESCAPE COLORS # ANSI BACKGROUND ESCAPE COLORS
WHITEBG='\033[1;47m' WHITEBG='\033[1;47m'
# FONT FORMAT EXCAPE CODES # FONT FORMAT EXCAPE CODES
BOLD='\e[1m' BOLD='\e[1m'
# Remember User's Starting Directory # Remember User's Starting Directory
PWD="$(pwd)" PWD="$(pwd)"
# Where Decks Are Located for linux & mac # Where Decks Are Located for linux & mac
# Prefer XDG Configuration before hard coded file paths # Prefer XDG Configuration before hard coded file paths
OS="$(uname)" OS="$(uname)"
case "$OS" in case "$OS" in
"Darwin") DIR="${XDG_DATA_HOME:-$HOME/Library/Application Support}/flash" && alias shuf=gshuf ;; "Darwin") DIR="${XDG_DATA_HOME:-$HOME/Library/Application Support}/flash" && alias shuf=gshuf ;;
"Linux") DIR="${XDG_DATA_HOME:-$HOME/.local/share}/flash" ;; "Linux") DIR="${XDG_DATA_HOME:-$HOME/.local/share}/flash" ;;
*) DIR="${XDG_DATA_HOME:-$HOME/.local/share}/flash" ;; *) DIR="${XDG_DATA_HOME:-$HOME/.local/share}/flash" ;;
esac esac
# Where the example deck will be placed and named # Where the example deck will be placed and named
EXAMPLE_DECK="$DIR/deck.csv" EXAMPLE_DECK="$DIR/deck.csv"
# Track High score # Track High score
HIGH_SCORE="$DIR/.highscore" HIGH_SCORE="$DIR/.highscore"
# Track number of cards reviewed per session # Track number of cards reviewed per session
REVIEW_LOG="$DIR/.reviews" REVIEW_LOG="$DIR/.reviews"
# Iterator for Count of cards reveiwed # Iterator for Count of cards reveiwed
COUNTER=0 COUNTER=0
# Success message of setup process # Success message of setup process
DIR_MADE_MSG=" DIR_MADE_MSG="
Your ${LRED}$DIR${NC} directory has been made and Your ${LRED}$DIR${NC} directory has been made and
@ -114,49 +114,45 @@ Science:What is the distance between the Earth and Sol called?:An Astronomical U
Programming:What is the best operating system?:Arch, because BTW i run Arch:999" Programming:What is the best operating system?:Arch, because BTW i run Arch:999"
# Define setup process in a function and create necessary files for user # Define setup process in a function and create necessary files for user
setup(){\ setup() {
mkdir "$DIR" && \ mkdir "$DIR" &&
touch {"$EXAMPLE_DECK","$HIGH_SCORE","$REVIEW_LOG"} && \ touch {"$EXAMPLE_DECK","$HIGH_SCORE","$REVIEW_LOG"} &&
echo "$DECK_TEMPLATE" >> "$EXAMPLE_DECK" && \ echo "$DECK_TEMPLATE" >>"$EXAMPLE_DECK" &&
echo -e "$DIR_MADE_MSG" ;} echo -e "$DIR_MADE_MSG"
}
# Test if .local/share exists and wether to offer setup process # Test if .local/share exists and wether to offer setup process
if [ ! -d "$DIR" ];then if [ ! -d "$DIR" ]; then
echo -e "No ${LRED}$DIR${NC} directory, make it? ${LGREEN}Y${NC}/${LRED}N${NC}" echo -e "No ${LRED}$DIR${NC} directory, make it? ${LGREEN}Y${NC}/${LRED}N${NC}"
# shellcheck disable=SC2162 # shellcheck disable=SC2162
read RESPONSE read RESPONSE
case "$RESPONSE" in case "$RESPONSE" in
[QqNn]) exit 0 ;; [QqNn]) exit 0 ;;
[Yy]) setup && exit 0 ;; [Yy]) setup && exit 0 ;;
*) echo -e "invalid choice, please select either ${LGREEN}y${NC} or ${LRED}n${NC}" && exit 1 ;; *) >&2 echo -e "invalid choice, please select either ${LGREEN}y${NC} or ${LRED}n${NC}" && exit 1 ;;
esac esac
fi fi
# go to the flashcard decks directory # go to the flashcard decks directory
cd "$DIR" || exit 1 cd "$DIR" || exit 1
# If there are no flashcard decks available return user to starting location # If there are no flashcard decks available return user to starting location
# while also displaying explanatory text of issue # while also displaying explanatory text of issue
if [ "$(find . -maxdepth "$SEARCH_DEPTH" -iname "*.csv" | wc -l)" = 0 ]; then [ "$(find . -maxdepth "$SEARCH_DEPTH" -iname "*.csv" | wc -l)" = 0 ] &&
echo -e "$NO_DECKS" && cd "$PWD" && exit 1 >&2 echo -e "$NO_DECKS" && exit 1
fi
# if highscore file was removed, remake it. # if highscore file was removed, remake it.
if [ ! -e "$HIGH_SCORE" ]; then [ ! -e "$HIGH_SCORE" ] && touch "$HIGH_SCORE"
touch "$HIGH_SCORE"
fi
# if reviewed file was removed, remake it. # if reviewed file was removed, remake it.
if [ ! -e "$REVIEW_LOG" ]; then [ ! -e "$REVIEW_LOG" ] && touch "$REVIEW_LOG"
touch "$REVIEW_LOG"
fi
print_usage() { print_usage() {
echo -e "\n${LCYAN}fla.sh --- Flash card system by Bryan Jenks${NC} ${LBLUE}<BryanJenks@protonmail.com>${NC}\n\n${YELLOW}${BOLD}Usage:${NC}\n\t${GREEN}flash -h:${NC} Print this help text\n\t${GREEN}flash -i:${NC} Print Information about the flashcard system\n\t${GREEN}flash -v:${NC} Print version Number\n\t${GREEN}flash -p [BINARY]:${NC} Change the previewer when selecting decks.\n\t\tDefault: ${GREEN}bat${NC}\n\t\tSupported: ${GREEN}bat${NC}, ${GREEN}cat${NC}\n" echo -e "\n${LCYAN}fla.sh --- Flash card system by Bryan Jenks${NC} ${LBLUE}<BryanJenks@protonmail.com>${NC}\n\n${YELLOW}${BOLD}Usage:${NC}\n\t${GREEN}flash -h:${NC} Print this help text\n\t${GREEN}flash -i:${NC} Print Information about the flashcard system\n\t${GREEN}flash -v:${NC} Print version Number\n\t${GREEN}flash -p [BINARY]:${NC} Change the previewer when selecting decks.\n\t\tDefault: ${GREEN}bat${NC}\n\t\tSupported: ${GREEN}bat${NC}, ${GREEN}cat${NC}\n"
} }
print_info() { print_info() {
echo -e "\nThis flash card system works via colon ${YELLOW}:${NC} seperated ${YELLOW}.csv${NC} files\n echo -e "\nThis flash card system works via colon ${YELLOW}:${NC} separated ${YELLOW}.csv${NC} files\n
with entries that look like this: ${LGREY}category:question:answer:0${NC}\n with entries that look like this: ${LGREY}category:question:answer:0${NC}\n
These ${YELLOW}.csv${NC} files should be stored in your These ${YELLOW}.csv${NC} files should be stored in your
@ -199,39 +195,38 @@ ${LCYAN}The Scoring System:${NC}\n
} }
while getopts 'hivp:' flag; do while getopts 'hivp:' flag; do
case "${flag}" in case "${flag}" in
h) print_usage && exit 0 ;; h) print_usage && exit 0 ;;
i) print_info && exit 0 ;; i) print_info && exit 0 ;;
v) echo -e "\n${YELLOW}fla.sh Current Version:${NC} ${RED}1.1${NC}\n" && exit 0 ;; v) echo -e "\n${YELLOW}fla.sh Current Version:${NC} ${RED}1.2${NC}\n" && exit 0 ;;
p) if [[ $(command -v "$OPTARG" 2>&1) ]]; then PREVIEWER=$OPTARG; else echo "Unable to find previewer $OPTARG. Exiting..." && exit 1; fi ;; p) { [[ $(command -v "$OPTARG" 2>&1) ]] && PREVIEWER=$OPTARG; } || >&2 echo "Unable to find previewer $OPTARG. Exiting..." && exit 1 ;;
*) print_usage && exit 1 ;; *) print_usage && exit 1 ;;
esac esac
done done
# Set some parameters for preview command used by FZF # Set some parameters for preview command used by FZF
while [ -z "$PREVIEWER_PARAMTERS" ]; do while [ -z "$PREVIEWER_PARAMTERS" ]; do
case "$PREVIEWER" in case "$PREVIEWER" in
bat) PREVIEWER_PARAMTERS="--theme='Solarized (dark)' --style=numbers --color=always" ;; bat) PREVIEWER_PARAMTERS="--theme='Solarized (dark)' --style=numbers --color=always" ;;
cat) PREVIEWER_PARAMTERS="--number" ;; cat) PREVIEWER_PARAMTERS="-b" ;;
*) echo -e "${RED}$PREVIEWER${NC} is not a valid previewer. Use '${GREEN}bat${NC}' or '${GREEN}cat${NC}'. Falling back on default...\n" && read -r -s -p 'Press [Enter] to continue...' && echo -e "\n" && PREVIEWER='bat' ;; *) echo -e "${RED}$PREVIEWER${NC} is not a valid previewer. Use '${GREEN}bat${NC}' or '${GREEN}cat${NC}'. Falling back on default...\n" && read -r -s -p 'Press [Enter] to continue...' && echo -e "\n" && PREVIEWER='bat' ;;
esac esac
done done
# Show pretty FZF preview of decks using $PREVIEWER. Default: BAT # Show pretty FZF preview of decks using $PREVIEWER. Default: BAT
DECK="$(find . -maxdepth "$SEARCH_DEPTH" -iname "*.csv" | fzf --preview="$PREVIEWER $PREVIEWER_PARAMTERS {} | head -500")" DECK="$(find . -maxdepth "$SEARCH_DEPTH" -iname "*.csv" | fzf --preview="$PREVIEWER $PREVIEWER_PARAMTERS {} | head -500")"
# Get current deck name for display # Get current deck name for display
case "$CURR_DECK_DISPLAY" in case "$CURR_DECK_DISPLAY" in
file) CURRENT_DECK="$(echo "$DECK" | awk -F/ '{print $NF}')" ;; file) CURRENT_DECK="$(echo "$DECK" | awk -F/ '{print $NF}')" ;;
path) CURRENT_DECK="$DECK" ;; path) CURRENT_DECK="$DECK" ;;
*) CURRENT_DECK="$(echo "$DECK" | awk -F/ '{print $NF}')" ;; *) CURRENT_DECK="$(echo "$DECK" | awk -F/ '{print $NF}')" ;;
esac esac
# The top part of the flash display so that code is not duplicated twice # The top part of the flash display so that code is not duplicated twice
print_head(){ print_head() {
QUESTION=$(echo "${q[1]}" | fold -w 59) QUESTION=$(echo "${q[1]}" | fold -w 59)
echo -e "${WHITEBG} Fla.sh - Flash Cards In Your Terminal ${NC} echo -e "${WHITEBG} Fla.sh - Flash Cards In Your Terminal ${NC}
${ORANGE}${BOLD} Current Deck:${BOLD}${NC}\t$(basename -s .csv "$CURRENT_DECK") ${ORANGE}${BOLD} Current Deck:${BOLD}${NC}\t$(basename -s .csv "$CURRENT_DECK")
@ -242,31 +237,29 @@ ${ORANGE}${BOLD}Cards Reviewed:${BOLD}${NC}\t$COUNTER
${LGREY}Category:${NC} ${q[0]} ${LGREY}Category:${NC} ${q[0]}
___________________________________________________________ ___________________________________________________________
$(if [ ${#QUESTION} -lt 59 ]; then printf "%$(( ( 59 - ${#QUESTION} ) / 2 ))s"; fi)$QUESTION" $([ ${#QUESTION} -lt 59 ] && printf "%$(((59 - ${#QUESTION}) / 2))s")$QUESTION"
} }
# Creating new entries in the log for the average score generation # Creating new entries in the log for the average score generation
add_usage_entry(){ add_usage_entry() {
if [ ! "$COUNTER" = 0 ]; then if [ ! "$COUNTER" = 0 ]; then
# Create a New Entry # Create a New Entry
TIME_STAMP=$(date +"%Y%m%d %H:%M:%S") TIME_STAMP=$(date +"%Y%m%d %H:%M:%S")
printf -v ENTRY "TimeStamp: %s Deck: %s cardsReviewed: %s" "$TIME_STAMP" "$CURRENT_DECK" "$COUNTER" printf -v ENTRY "TimeStamp: %s Deck: %s cardsReviewed: %s" "$TIME_STAMP" "$CURRENT_DECK" "$COUNTER"
echo "$ENTRY" >> "$REVIEW_LOG" echo "$ENTRY" >>"$REVIEW_LOG"
fi fi
} }
# If no deck is selected in fzf menu # If no deck is selected in fzf menu
# return user to start location # return user to start location
# and exit quietly # and exit quietly
if [ -z "$DECK" ]; then [ -z "$DECK" ] && clear && exit 1
clear && cd "$PWD" && exit 1
fi
main(){ main() {
IFS=$':' IFS=$':'
# shellcheck disable=SC2162 # shellcheck disable=SC2162
read -a q <<< "$(sort "$DECK" -n --field-separator=: --key=4 | head -n "$CARD_POOL_SIZE"| shuf -n 1)" read -a q <<<"$(sort "$DECK" -n --field-separator=: --key=4 | head -n "$CARD_POOL_SIZE" | shuf -n 1)"
clear clear
print_head print_head
echo -e " echo -e "
@ -279,15 +272,13 @@ ${LGREY}──────────────── Press [Enter] to contin
done done
clear clear
print_head print_head
if [ "$NEXT" = q ] || [ "$NEXT" = Q ]; then { [ "$NEXT" = q ] || [ "$NEXT" = Q ]; } && add_usage_entry && clear && exit 0
add_usage_entry && cd "$PWD" && clear && exit 0
fi
ANSWER=$(echo "${q[2]}" | fold -w 59) ANSWER=$(echo "${q[2]}" | fold -w 59)
echo -e "___________________________________________________________ echo -e "___________________________________________________________
$(if [ ${#ANSWER} -lt 59 ]; then printf "%$(( ( 59 - ${#ANSWER} ) / 2 ))s"; fi)$ANSWER $([ ${#ANSWER} -lt 59 ] && printf "%$(((59 - ${#ANSWER}) / 2))s")$ANSWER
${WHITEBG}${WHITE}===========================================================${NC} ${WHITEBG}${WHITE}===========================================================${NC}
@ -302,59 +293,54 @@ ${LGREY}Select a number to continue, or${NC} ${LRED}Q${NC} ${LGREY}to quit...${N
# shellcheck disable=SC2162 # shellcheck disable=SC2162
read -sn 1 DIFFICULTY_SCORE read -sn 1 DIFFICULTY_SCORE
done done
if [ "$DIFFICULTY_SCORE" = q ] || [ "$DIFFICULTY_SCORE" = Q ]; then { [ "$DIFFICULTY_SCORE" = q ] || [ "$DIFFICULTY_SCORE" = Q ]; } &&
add_usage_entry && cd "$PWD" && clear && exit 0 add_usage_entry && clear && exit 0
fi
clear clear
COUNTER="$((COUNTER+1))" # Increment count for card review count increment COUNTER="$((COUNTER + 1))" # Increment count for card review count increment
if [ "${q[3]}" = 0 ]; then if [ "${q[3]}" = 0 ]; then
NEW_ITEM_SCORE=0 NEW_ITEM_SCORE=0
case "$DIFFICULTY_SCORE" in case "$DIFFICULTY_SCORE" in
[123]) NEW_ITEM_SCORE=0 ;;#HARD DIFFICULTY & NORMAL [123]) NEW_ITEM_SCORE=0 ;; #HARD DIFFICULTY & NORMAL
4) NEW_ITEM_SCORE=1 ;;#MILD 4) NEW_ITEM_SCORE=1 ;; #MILD
5) NEW_ITEM_SCORE=2 ;;#EASY 5) NEW_ITEM_SCORE=2 ;; #EASY
*) NEW_ITEM_SCORE=0 ;;#INVALID *) NEW_ITEM_SCORE=0 ;; #INVALID
esac esac
elif [ "${q[3]}" = 1 ]; then elif [ "${q[3]}" = 1 ]; then
case "$DIFFICULTY_SCORE" in case "$DIFFICULTY_SCORE" in
1) NEW_ITEM_SCORE=0 ;;#HARD 1) NEW_ITEM_SCORE=0 ;; #HARD
2) NEW_ITEM_SCORE=0 ;;#DIFFICULT 2) NEW_ITEM_SCORE=0 ;; #DIFFICULT
3) NEW_ITEM_SCORE=1 ;;#NORMAL 3) NEW_ITEM_SCORE=1 ;; #NORMAL
4) NEW_ITEM_SCORE=2 ;;#MILD 4) NEW_ITEM_SCORE=2 ;; #MILD
5) NEW_ITEM_SCORE=3 ;;#EASY 5) NEW_ITEM_SCORE=3 ;; #EASY
*) NEW_ITEM_SCORE=1 ;;#INVALID *) NEW_ITEM_SCORE=1 ;; #INVALID
esac esac
else else
case "$DIFFICULTY_SCORE" in case "$DIFFICULTY_SCORE" in
1) NEW_ITEM_SCORE="$((q[3]-2))" ;;#HARD 1) NEW_ITEM_SCORE="$((q[3] - 2))" ;; #HARD
2) NEW_ITEM_SCORE="$((q[3]-1))" ;;#DIFFICULTY 2) NEW_ITEM_SCORE="$((q[3] - 1))" ;; #DIFFICULTY
3) NEW_ITEM_SCORE="${q[3]}" ;;#NORMAL 3) NEW_ITEM_SCORE="${q[3]}" ;; #NORMAL
4) NEW_ITEM_SCORE="$((q[3]+1))" ;;#MILD 4) NEW_ITEM_SCORE="$((q[3] + 1))" ;; #MILD
5) NEW_ITEM_SCORE="$((q[3]+2))" ;;#EASY 5) NEW_ITEM_SCORE="$((q[3] + 2))" ;; #EASY
*) NEW_ITEM_SCORE="${q[3]}" ;;#INVALID *) NEW_ITEM_SCORE="${q[3]}" ;; #INVALID
esac esac
fi fi
# Update item score for each flashcard item # Update item score for each flashcard item
## Remove forward slashes in the Questions and answers ## Remove forward slashes in the Questions and answers
QUESTION_REGEX=$(sed "s/\(\/\|\[\|\]\|\*\)/\\\\\1/g" <<< "${q[1]}")
ANSWER_REGEX=$(sed "s/\(\/\|\[\|\]\|\*\)/\\\\\1/g" <<< "${q[2]}") QUESTION_REGEX="$(sed "s/\(\/\|\[\|\]\|\*\)/\\\\\1/g" <<<"${q[1]}")"
sed -i "s/${q[0]}:$QUESTION_REGEX:$ANSWER_REGEX:${q[3]}/${q[0]}:$QUESTION_REGEX:$ANSWER_REGEX:$NEW_ITEM_SCORE/g" "$DECK" ANSWER_REGEX="$(sed "s/\(\/\|\[\|\]\|\*\)/\\\\\1/g" <<<"${q[2]}")"
sed -i "s/${q[0]}:$QUESTION_REGEX:$ANSWER_REGEX:${q[3]}/${q[0]}:$QUESTION_REGEX:$ANSWER_REGEX:$NEW_ITEM_SCORE/g" "$DECK"
# If no highscore currently set, set it. # If no highscore currently set, set it.
if [ -z "$(cat "$HIGH_SCORE")" ]; then [ -z "$(cat "$HIGH_SCORE")" ] && echo "$COUNTER" >"$HIGH_SCORE"
echo "$COUNTER" > "$HIGH_SCORE"
fi
# If Cards Reviewed > Current High Score, Update # If Cards Reviewed > Current High Score, Update
if [ "$COUNTER" -gt "$(cat "$HIGH_SCORE")" ]; then [ "$COUNTER" -gt "$(cat "$HIGH_SCORE")" ] && echo "$COUNTER" >"$HIGH_SCORE"
echo "$COUNTER" > "$HIGH_SCORE"
fi
} }
while true; do while true; do
main main
done done