diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e69de29
diff --git a/EXTENSIONS.md b/EXTENSIONS.md
new file mode 100644
index 0000000..4a7f978
--- /dev/null
+++ b/EXTENSIONS.md
@@ -0,0 +1,225 @@
+# tifmx - extend tifm to your liking
+we call the extension framework bundled with tifm, `tifmx`, short for `tiny file manager extensions` (creative naming!).
+
+tifmx automatically loads extensions placed in the `extensions` folder, allowing you to drop in extensions to add them in.
+
+it also provides a couple of functions for tifm to adapt its behaviour to your extension.
+
+## guide
+here we will create a very simple greeter extension to show you how easy it is to write an extension for tifm.
+
+### init event
+we'll start by creating a `greeter.sh` file in the `extensions` folder.
+then, we'll listen for the `init` event which is called when the extension is loaded.
+events are function definitions of this format: `ext_name.event_name`. tifmx automatically figures out the extension's name by reading the file name, so we will create our init event like this:
+```bash
+greeter.init() {
+ # code here
+}
+```
+then, we will simply print "Hello, $USERNAME!" to the console:
+```bash
+greeter.init() {
+ echo "Hello, $USERNAME!"
+}
+```
+you can test it out by launching tifm now.
+
+### simple command
+simple commands are when you press a key and a function gets executed. we'll bind our `h` key to say `Hey all!` when it is pressed.
+
+we'll first start by defining our function. it can be named anything, because we will bind it using its name later; we'll call it `greet_all`:
+```sh
+greeter.init() {
+ echo "Hello, $USERNAME!"
+}
+
+# NEW
+greet_all() {
+ echo "Hey all!"
+}
+```
+awesome. but now, if you reload tifm and press the `h` key, you will get an error. this is because we haven't told tifm to listen to the key.
+
+we will need to use the `tifmx.bind` command to create a binding and link it to our function. you create a binding this way:
+```sh
+tifmx.bind char func
+```
+so to bind our new `greet_all` function to the `h` key:
+```sh
+tifmx.bind h greet_all
+```
+now your file should look like this:
+```sh
+greeter.init() {
+ echo "Hello, $USERNAME!"
+}
+
+greet_all() {
+ echo "Hey all!"
+}
+# NEW
+tifmx.bind h greet_all
+```
+you can now reload tifm and press `h` to see a nice greeting!
+
+### long command
+long commands are when you press a key to access a group, and then press another key to run a sub command. examples include `rd` (remove directory) and `nf` (new file).
+
+we'll make two commands: `gu` to greet the user and `gw` to greet the world. we can do this using the `tifmx.add_long` and `tifmx.bind_sub` commands. you create a binding this way:
+```sh
+tifmx.add_long char1
+tifmx.bind_sub char1 char2 func
+# you can add infinite subcommands to a group
+```
+we have already defined a function that greets the user: `greeter.init`, so in our case we can use it. but we'll create a greet world function first:
+```sh
+greeter.init() {
+ echo "Hello, $USERNAME!"
+}
+
+greet_all() {
+ echo "Hey all!"
+}
+tifmx.bind h greet_all
+
+# NEW
+greet_world() {
+ echo "Hello, world!"
+}
+```
+
+and now we'll create our long command:
+```sh
+greeter.init() {
+ echo "Hello, $USERNAME!"
+}
+
+greet_all() {
+ echo "Hey all!"
+}
+tifmx.bind h greet_all
+
+greet_world() {
+ echo "Hello, world!"
+}
+# NEW
+tifmx.add_long g
+tifmx.bind_sub g u greeter.init
+tifmx.bind_sub g w greet_world
+```
+you can now reload and test your long command out!
+
+## documentation
+extensions have access to everything defined in the configuration file and pretty much every aspect of tifm.
+### events
+events are functions defined in your extension that get called when a specific action happens inside of tifm. you define them this way: `extension.event` where extension is the name of your extension file (without `.sh`) and `event` is the name of your event. see below for all available events.
+> **Note:** parameters are passed without name and are accessible via `$1`, `$2` and so on, or `"${@[n]}"` where `n` is a number.
+#### `extension.init()`
+called when your extension is loaded.
+
+#### `extension.display()` (provided you're using the default `__TIFM_DISPLAY` in `config.sh`)
+called when the display (top part of the command input) is displayed. whatever it echoes last will be added as a widget in the display.
+
+example: quick clock extension:
+```sh
+# file: extensions/clock.sh
+clock.display() {
+ # display clock
+ echo -e "$CYAN$(date +"%H:%M")$NORMAL"
+}
+```
+
+#### `extension.nav(directory)`
+called when the user changes directories, at the very end of the `N` command.
+
+parameters:
+* `directory`: the directory the user travelled to
+
+#### `extension.edit(file)`
+called when the user edits a file, at the very end of the `e` command.
+
+parameters:
+* `file`: the file the user edited
+
+#### `extension.copy(from, to)`
+called when the user copies a file, at the very end of the `c` command.
+
+parameters:
+* `from`: the file the user copied
+* `to`: the location the file was copied to
+
+#### `extension.move(from, to)`
+called when the user moves a file, at the very end of the `m` command.
+
+parameters:
+* `from`: the file the user moved
+* `to`: the location the file was moved to
+
+#### `extension.mkdir(dir)` / `extension.mkfile(file)`
+called when the user creates a directory/file, at the very end of the `n(d/f)` command.
+
+parameters (`mkdir`):
+* `dir`: the directory the user created
+
+parameters (`mkfile`):
+* `file`: the file the user created
+
+#### `extension.rmdir(dir)` / `extension.rmfile(file)`
+called when the user deletes a directory/file, at the very end of the `r(d/f)` command.
+
+parameters (`rmdir`):
+* `dir`: the directory the user deleted
+
+parameters (`rmfile`):
+* `file`: the file the user deleted
+
+#### `extension.fperms(item, permissions)`
+called when the user changes the permissions of a file, at the very end of the `P` command.
+
+parameters:
+* `item`: the file or directory for which the permissions were modified
+* `permissions`: the permission arguments given to the file (in chmod format)
+
+### functions
+you have access to multiple functions that change the behaviour of tifm.
+#### `tifmx.bind(char, func)`
+tells tifm to listen to when `char` is pressed, and in that case call `func`.
+example:
+```sh
+go_home() { # navigate to the home directory
+ cd ~
+}
+tifmx.bind "~" go_home
+```
+
+#### `tifmx.add_long(char)`
+tells tifm to listen to when `char` is pressed, and in that case wait for another keypress and find a command associated to that combination. must be used with `tifmx.bind_sub(char1, char2, func)`.
+
+#### `tifmx.bind_sub(char1, char2, func)`
+tells tifmx to associate the combination `char1 + char2` to call `func`.
+example:
+```sh
+go_home() {
+ cd ~
+}
+go_parent() {
+ cd ..
+}
+tifmx.add_long "~"
+tifmx.bind_sub "~" "~" go_home # pressing ~ then ~ will return home
+tifmx.bind_sub "~" "<" go_parent # pressing ~ then < will return to the parent directory
+```
+
+#### `tifmx.add_help(char, helpstring)`
+adds a custom line in the `?` command to show the usage of your custom command.
+example:
+```sh
+go_home() {
+ cd ~
+}
+tifmx.bind "~" go_home
+tifmx.add_help "~" "return to the parent directory"
+# will show like this:
+# ~ - return to the parent directory
+```
\ No newline at end of file
diff --git a/README.md b/README.md
index 6958c80..9edb319 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,3 @@
-# linfm
-Some sort of File Manager, made in the bash interpreter
-
-
-
-Package name: linfm
+# tifm
+a really **ti**ny **f**ile **m**anager
+mostly meant for personal use and contribution to the parent project
diff --git a/config.sh b/config.sh
new file mode 100644
index 0000000..2c3d23b
--- /dev/null
+++ b/config.sh
@@ -0,0 +1,31 @@
+__TIFM_PAGER="less" # [p]eek command
+__TIFM_EDITOR="nano" # [e]dit command
+__ANGLE_UP_RIGHT="╭"
+__ANGLE_UP_LEFT="╮"
+__ANGLE_DOWN_RIGHT="╰"
+__ANGLE_DOWN_LEFT="╯"
+__VBAR="│"
+__TIFM_DECO_COLOUR="$CYAN"
+__TIFM_CONFIRM_RETURN=true
+__TIFM_DISPLAY() {
+ local stat=""
+ if [ "$STATUS" == "0" ]; then
+ stat="${GREEN}✔$NORMAL"
+ else
+ stat="${RED}✘ $STATUS$NORMAL"
+ fi
+ local string="$GREEN$BRIGHT$PWD$NORMAL $stat "
+ # for each extension, if it has a display function, call it
+ for ext_name in "${tifm_extensions[@]}"; do
+ if type "$ext_name".display &> /dev/null; then
+ string="$string$( "$ext_name".display )$NORMAL "
+ fi
+ done
+ echo "$string"
+}
+__TIFM_LS_COLOUR_FILE="$BLUE"
+__TIFM_LS_COLOUR_DIRECTORY="$LIME_YELLOW"
+__TIFM_PROMPT() {
+ user=$(whoami)
+ echo "$CYAN$user>"
+}
\ No newline at end of file
diff --git a/extension_ignore b/extension_ignore
new file mode 100644
index 0000000..e69de29
diff --git a/extensions/clock.sh b/extensions/clock.sh
new file mode 100644
index 0000000..ae414f6
--- /dev/null
+++ b/extensions/clock.sh
@@ -0,0 +1,4 @@
+clock.display() {
+ # display clock
+ echo -e "$CYAN$(date +"%H:%M")$NORMAL"
+}
\ No newline at end of file
diff --git a/extensions/git.sh b/extensions/git.sh
new file mode 100644
index 0000000..1650472
--- /dev/null
+++ b/extensions/git.sh
@@ -0,0 +1,130 @@
+# git.sh
+# adds git support to tifm
+
+__tifmgit_in_repo=false
+is_git_repo() {
+ # check if current directory is a git repo
+ git rev-parse --is-inside-work-tree &> /dev/null
+}
+
+git.init() {
+ # check if current directory is a git repo
+ if is_git_repo; then
+ __tifmgit_in_repo=true
+ fi
+}
+
+git.nav() {
+ if is_git_repo; then
+ __tifmgit_in_repo=true
+ fi
+}
+
+git.display() {
+ # display git status
+ if $__tifmgit_in_repo; then
+ local branch=$(git rev-parse --abbrev-ref HEAD)
+ local gstatus=$(git status --porcelain)
+ # remove leading and trailing spaces
+ gstatus=$(echo "$gstatus" | sed 's/^ *//g;s/ *$//g')
+ # remove leading and trailing newlines
+ gstatus=$(echo "$gstatus" | sed 's/^\n//g;s/\n$//g')
+ if [[ -z "$gstatus" ]]; then
+ gstatus=0
+ else
+ # replace with count
+ gstatus=$(echo "$gstatus" | wc -l)
+ fi
+ local modif="modif"
+ # if modif > 1, replace with "modifs"
+ if [[ "$gstatus" -gt 1 ]]; then
+ modif="modifs"
+ fi
+ echo "$BRIGHT$YELLOW(git branch $branch - status: $gstatus $modif)$NORMAL"
+ fi
+}
+
+git_pull() {
+ # pull from remote
+ git pull
+}
+git_push() {
+ # push to remote
+ git push
+}
+git_status() {
+ # display git status
+ if $__tifmgit_in_repo; then
+ local branch=$(git rev-parse --abbrev-ref HEAD)
+ local gstatus=$(git status --porcelain)
+ # colouring
+ # M file -> ${BLUE}M${NORMAL}file
+ gstatus=$(echo "$gstatus" | sed "s/ M /${BLUE}M${NORMAL} /g")
+ # A file -> ${GREEN}A${NORMAL}file
+ gstatus=$(echo "$gstatus" | sed "s/ A /${GREEN}A${NORMAL} /g")
+ # D file -> ${RED}D${NORMAL}file
+ gstatus=$(echo "$gstatus" | sed "s/ D /${RED}D${NORMAL} /g")
+ # R file -> ${YELLOW}R${NORMAL}file
+ gstatus=$(echo "$gstatus" | sed "s/ R /${YELLOW}R${NORMAL} /g")
+ # C file -> ${LIME_YELLOW}C${NORMAL}file
+ gstatus=$(echo "$gstatus" | sed "s/ C /${LIME_YELLOW}C${NORMAL} /g")
+ # U file -> ${POWDER_BLUE}U${NORMAL}file
+ gstatus=$(echo "$gstatus" | sed "s/ U /${POWDER_BLUE}U${NORMAL} /g")
+ # ? file -> ${MAGENTA}?${NORMAL}file
+ gstatus=$(echo "$gstatus" | sed "s/ ? /${MAGENTA}?${NORMAL} /g")
+ # ! file -> ${CYAN}!${NORMAL}file
+ gstatus=$(echo "$gstatus" | sed "s/ ! /${CYAN}!${NORMAL} /g")
+ # if gstatus is empty, replace it with "nothing to commit"
+ if [ -z "$gstatus" ]; then
+ gstatus="nothing to commit"
+ fi
+ echo -e "$BRIGHT${YELLOW}git branch $branch$NORMAL\n$gstatus"
+ fi
+}
+git_add() {
+ # add all files to git
+ git add .
+}
+git_commit() {
+ # commit all files to git
+ read -p "Commit message: " message
+ git commit -m "$message"
+}
+git_diff() {
+ # show diff between current and previous commit
+ git diff
+}
+git_log() {
+ # show log of all commits
+ git log
+}
+git_log_last() {
+ # show log of last commit
+ git log -1
+}
+git_full() { # pull, add, commit, push
+ git_pull
+ git_add
+ git_commit
+ git_push
+}
+git_view_remote() {
+ git remote -v
+}
+git_clone() {
+ read -p "Git URL: " url
+ git clone "$url"
+}
+tifmx.add_long G # for global git commands
+tifmx.bind_sub G C git_clone
+tifmx.bind_sub G p git_pull
+tifmx.bind_sub G P git_push
+tifmx.bind_sub G s git_status
+tifmx.bind_sub G a git_add
+tifmx.bind_sub G c git_commit
+tifmx.bind_sub G d git_diff
+tifmx.bind_sub G l git_log
+tifmx.bind_sub G L git_log_last
+tifmx.bind_sub G "*" git_full
+tifmx.bind_sub G r git_view_remote
+tifmx.add_help G "git commands integration ([C]lone, [p]ull, [P]ush, [s]tatus, [a]dd, [c]ommit, [d]iff, [l]og, [L]og last, [*]full, [r]emote)"
\ No newline at end of file
diff --git a/installer.sh b/installer.sh
new file mode 100644
index 0000000..b23dcbf
--- /dev/null
+++ b/installer.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+# TIFM installer script
+# run by using {sudo curl -sL https://raw.githubusercontent.com/Rexxt/tifm/master/installer.sh | bash}
+
+# make sure git is installed
+if ! type git &> /dev/null; then
+ echo "git is not installed"
+ exit 1
+fi
+
+git clone "https://github.com/Rexxt/tifm.git"
+rm tifm/installer.sh
+mkdir -p ~/tifm
+mv tifm ~
+echo "where should we install tifm?"
+echo "1) /usr/local/bin"
+echo "2) /usr/bin"
+read -p "> " -n 1 -r reply
+echo
+case "$reply" in
+ 1)
+ echo "installing to /usr/local/bin"
+ sudo touch /usr/local/bin/tifm
+ echo "~/tifm/main.sh" > /usr/local/bin/tifm
+ sudo chmod +x ~/tifm/main.sh
+ sudo chmod +x /usr/local/bin/tifm
+ ;;
+ 2)
+ echo "installing to /usr/bin"
+ sudo touch /usr/bin/tifm
+ echo "~/tifm/main.sh" > /usr/bin/tifm
+ sudo chmod +x ~/tifm/main.sh
+ sudo chmod +x /usr/bin/tifm
+ ;;
+ *)
+ echo "invalid option"
+ exit 1
+ ;;
+esac
+# check if tifm command is in path
+if ! type tifm &> /dev/null; then
+ echo "tifm is not in path... this is most likely a problem on our side."
+ exit 1
+else
+ echo "tifm is installed and usable!"
+fi
diff --git a/main.sh b/main.sh
index f7c1be1..576a5b4 100644
--- a/main.sh
+++ b/main.sh
@@ -1,124 +1,444 @@
#!/bin/env bash
-clear
-echo "
-┌─────────────────────────────────────────────────┐
-│ %#### │
-│ ######### │
-│ @@@###@@# LinFM │
-│ @@@@@@@@@ A file manager, in your command line. │
-│ Made with <3 by [I> (Icycoide) │
-└─────────────────────────────────────────────────┘
-"
-sleep 3
-echo "Loading contents from " $PWD"..."
+declare -a -x tifm_extensions
+declare -A -x tifm_extensions_commands
+declare -a -x tifm_extensions_commands_list
+declare -A -x tifm_extensions_commands_help
+declare -a -x tifm_extensions_longcommands
+declare -A -x tifm_extensions_subcommands
+tifmx.bind() {
+ tifm_extensions_commands["$1"]="$2"
+}
+tifmx.add_long() {
+ tifm_extensions_longcommands+=("$1")
+}
+tifmx.bind_sub() {
+ tifm_extensions_subcommands["$1$2"]="$3"
+}
+tifmx.add_help() {
+ tifm_extensions_commands_list+=("$1")
+ tifm_extensions_commands_help["$1"]="$2"
+}
+# consts
+__TIFM_VERSION="0.2.1"
+BLACK=$(tput setaf 0)
+RED=$(tput setaf 1)
+GREEN=$(tput setaf 2)
+YELLOW=$(tput setaf 3)
+LIME_YELLOW=$(tput setaf 190)
+POWDER_BLUE=$(tput setaf 153)
+BLUE=$(tput setaf 4)
+MAGENTA=$(tput setaf 5)
+CYAN=$(tput setaf 6)
+WHITE=$(tput setaf 7)
+BRIGHT=$(tput bold)
+NORMAL=$(tput sgr0)
+BLINK=$(tput blink)
+REVERSE=$(tput smso)
+UNDERLINE=$(tput smul)
+DIM=$(tput dim)
+SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
+
+init() {
+ # vars
+ STATUS=0
+ # config
+ source "$SCRIPT_DIR/config.sh"
+ # load extensions
+ tput sc
+ printf "Loading extensions... "
+ load_extensions
+ printf "Done.\n"
+}
+
+load_extensions() {
+ local count=0
+ # check how many files are in the extensions directory
+ local files=$(ls -1 "$SCRIPT_DIR/extensions" | wc -l)
+ for extension in "$SCRIPT_DIR/extensions/"*".sh"; do
+ # if there is no save folder, create it
+ if [ ! -d "$SCRIPT_DIR/save" ]; then
+ mkdir "$SCRIPT_DIR/save"
+ fi
+ local ext_name=$(basename "$extension" | cut -d. -f1)
+ # if the name is in the extension_ignore file, skip it
+ if grep -q "$ext_name" "$SCRIPT_DIR/extension_ignore"; then
+ continue
+ fi
+ source "$extension"
+ # add only the name of the extension to the array (ex: extensions/git.sh -> git)
+ tifm_extensions+=("$ext_name")
+ count=$((count + 1))
+ # percentage of completion
+ local percent=$((count / files * 100))
+ tput rc
+ printf "Loading extensions... $count/$files ($percent%%)\n"
+ # if function $ext_name.init exists, call it
+ if type "$ext_name".init &> /dev/null; then
+ "$ext_name".init
+ fi
+ done
+}
-clear
main() {
- echo "┌─ Waiting for action at" $PWD
- read -p "└─linfm> " lfm_ans
- case "$lfm_ans" in
- SetDir)
- echo "Select a directory to go to."
- read lfm_setdir
- cd $lfm_setdir
- main
- ;;
- Open)
- echo "Choose a file to open."
- read lfm_setfile
- xdg-open $lfm_setfile
- main
- ;;
- Copy)
- echo "Choose the file and the location you would like to copy it to."
- read lfm_setfile
- cp $lfm_setfile
- main
- ;;
- MoveFile)
- echo "Choose the file and the new location you would like to move it to, with both of them being separated with a space."
- read lfm_setfile
- mv $lfm_setfile
- main
- ;;
- Index)
- ls -a
- main
- ;;
- CreateFolder)
- echo "Please put in the name of the folder you would like to create."
- read lfm_setdir
- mkdir $lfm_setdir
- main
- ;;
- DeleteFile)
- echo "Select the file you would like to delete. (Without confirmation.) To cancel, just press enter without typing in anything."
- read lfm_setfile
- rm $lfm_setfile
- main
- ;;
- DeleteFolder)
- echo "Select the folder you would like to delete. (Without confirmation.) To cancel, just press enter without typing in anything."
- read lfm_setdir
- rm -rf $lfm_setdir
- main
- ;;
- TouchFile)
- echo "Choose the name of the file..."
- read lfm_setfile
- touch $lfm_setfile
- main
- ;;
- PermSet)
- echo "Choose a file or folder to change the permission"
- read lfm_setany
- echo "Choose the arguments from 'chmod' to set as permission for the file or folder. (Read the manual for chmod for more info)"
- read lfm_setperm
- chmod $lfm_setperm $lfm_setany
- main
- ;;
- CmdLine)
- /bin/sh
- main
- ;;
- Help)
- echo "
- List of commands:
- SetDir
- -Goes to a folder
- Open
- -Opens a file
- MoveFile
- -Moves/Renames a file
- Copy
- -Copies a file to a location
- Index
- -Shows the list of files inside the directory
- CreateFolder
- -Creates a folder
- DeleteFile
- -Deletes a File
- DeleteFolder
- -Deletes folder
- TouchFile
- -Creates new file
- PermSet
- -Sets permissions for a specific file or folder
- CmdLine
- -Switches to command line mode, run 'exit' to exit.
- Exit
- -That exits out of LinFM."
- main
- ;;
- Exit)
- clear
- exit
- ;;
- *)
- echo "Unrecognized command. Type 'Help' for a list of commands."
- main
- ;;
- esac
+ echo "$__TIFM_DECO_COLOUR$__ANGLE_UP_RIGHT $(__TIFM_DISPLAY)$NORMAL"
+ while read file; do
+ __color="$__TIFM_LS_COLOUR_FILE"
+ __post=""
+ __icon="🗎"
+ if [ -d "$file" ]; then
+ __color="$__TIFM_LS_COLOUR_DIRECTORY"
+ __post="/"
+ __icon="␣"
+ fi
+ echo "$__TIFM_DECO_COLOUR$__VBAR$__color $__icon $file$__post$NORMAL"
+ done < <(ls -a)
+ read -n 1 -p "$__TIFM_DECO_COLOUR$__ANGLE_DOWN_RIGHT $(__TIFM_PROMPT) $YELLOW" ans
+
+ if [[ "$ans" != "n" ]] && [[ "$ans" != "r" ]] && [[ "$ans" != ";" ]] && [[ ! "${tifm_extensions_longcommands[*]}" =~ "$ans" ]]; then
+ echo ""
+ fi
+ printf "$NORMAL"
+
+ # command execution
+ case "$ans" in
+ N)
+ echo "Select a directory to go to (leave blank to cancel)."
+ read -p "nav:: " tifm_dir
+ if [[ "$tifm_dir" == "" ]]; then
+ echo "Cancelled."
+ return
+ else
+ cd $tifm_dir
+ # for every extension, if it has a function called name.nav, call it
+ for ext_name in "${tifm_extensions[@]}"; do
+ if type "$ext_name".nav &> /dev/null; then
+ "$ext_name".nav "$tifm_dir"
+ fi
+ done
+ fi
+ ;;
+ o)
+ echo "Choose a file to open (leave blank to cancel)."
+ read -p "file:: " tifm_file
+ if [[ "$tifm_file" == "" ]]; then
+ echo "Cancelled."
+ return
+ else
+ xdg-open $tifm_file
+ fi
+ ;;
+ p)
+ echo "Choose a file to view (leave blank to cancel)."
+ read -p "file:: " tifm_file
+ if [[ "$tifm_file" == "" ]]; then
+ echo "Cancelled."
+ return
+ else
+ $__TIFM_PAGER $tifm_file
+ fi
+ ;;
+ e)
+ echo "Choose a file to edit (leave blank to cancel)."
+ read -p "file:: " tifm_file
+ if [[ "$tifm_file" == "" ]]; then
+ echo "Cancelled."
+ return
+ else
+ $__TIFM_EDITOR $tifm_file
+ fi
+ # for every extension, if it has a function called name.edit, call it
+ for ext_name in "${tifm_extensions[@]}"; do
+ if type "$ext_name".edit &> /dev/null; then
+ "$ext_name".edit "$tifm_file"
+ fi
+ done
+ ;;
+ c)
+ echo "Choose the file and the location you would like to copy it to (leave blank to cancel)."
+ read -p "from:: " tifm_file_from
+ if [[ "$tifm_file_from" == "" ]]; then
+ echo "Cancelled."
+ return
+ fi
+ read -p "to:: " tifm_file_to
+ if [[ "$tifm_file_to" == "" ]]; then
+ echo "Cancelled."
+ return
+ fi
+ cp "$tifm_file_from" "$tifm_file_to"
+ # for every extension, if it has a function called name.copy, call it
+ for ext_name in "${tifm_extensions[@]}"; do
+ if type "$ext_name".copy &> /dev/null; then
+ "$ext_name".copy "$tifm_file_from" "$tifm_file_to"
+ fi
+ done
+ ;;
+ m)
+ echo "Choose the file and the new location you would like to move it to."
+ read -p "from:: " tifm_file_from
+ if [[ "$tifm_file_from" == "" ]]; then
+ echo "Cancelled."
+ return
+ fi
+ read -p "to:: " tifm_file_to
+ if [[ "$tifm_file_to" == "" ]]; then
+ echo "Cancelled."
+ return
+ fi
+ mv "$tifm_file_from" "$tifm_file_to"
+ # for every extension, if it has a function called name.move, call it
+ for ext_name in "${tifm_extensions[@]}"; do
+ if type "$ext_name".move &> /dev/null; then
+ "$ext_name".move "$tifm_file_from" "$tifm_file_to"
+ fi
+ done
+ ;;
+ i)
+ echo "Choose the directory to inspect (leave blank to cancel)."
+ read -p "dir:: " tifm_dir
+ if [[ "$tifm_dir" == "" ]]; then
+ echo "Cancelled."
+ return
+ else
+ ls -l $tifm_dir | $__TIFM_PAGER
+ fi
+ ;;
+ n)
+ read -n 1 tifm_type
+ echo ""
+ case "$tifm_type" in
+ d)
+ echo "Choose the directory you would like to create (leave blank to cancel)."
+ read -p "name:: " tifm_dir_name
+ if [[ "$tifm_dir_name" == "" ]]; then
+ echo "Cancelled."
+ return
+ fi
+ mkdir "$tifm_dir_name"
+ # for every extension, if it has a function called name.mkdir, call it
+ for ext_name in "${tifm_extensions[@]}"; do
+ if type "$ext_name".mkdir &> /dev/null; then
+ "$ext_name".mkdir "$tifm_dir_name"
+ fi
+ done
+ ;;
+ f)
+ echo "Choose the file you would like to create (leave blank to cancel)."
+ read -p "name:: " tifm_file_name
+ if [[ "$tifm_file_name" == "" ]]; then
+ echo "Cancelled."
+ return
+ fi
+ touch "$tifm_file_name"
+ # for every extension, if it has a function called name.mkfile, call it
+ for ext_name in "${tifm_extensions[@]}"; do
+ if type "$ext_name".mkfile &> /dev/null; then
+ "$ext_name".mkfile "$tifm_file_name"
+ fi
+ done
+ ;;
+ *)
+ echo "Invalid type ([d]irectory/[f]ile)."
+ ;;
+ esac
+ ;;
+ r)
+ read -n 1 tifm_type
+ echo ""
+ case "$tifm_type" in
+ d)
+ echo "Choose the directory you would like to remove (leave blank to cancel)."
+ read -p "name:: " tifm_dir_name
+ if [[ "$tifm_dir_name" == "" ]]; then
+ echo "Cancelled."
+ return
+ fi
+ rm -rf "$tifm_dir_name"
+ # for every extension, if it has a function called name.rmdir, call it
+ for ext_name in "${tifm_extensions[@]}"; do
+ if type "$ext_name".rmdir &> /dev/null; then
+ "$ext_name".rmdir "$tifm_dir_name"
+ fi
+ done
+ ;;
+ f)
+ echo "Choose the file you would like to remove (leave blank to cancel)."
+ read -p "name:: " tifm_file_name
+ if [[ "$tifm_file_name" == "" ]]; then
+ echo "Cancelled."
+ return
+ fi
+ rm "$tifm_file_name"
+ # for every extension, if it has a function called name.rmfile, call it
+ for ext_name in "${tifm_extensions[@]}"; do
+ if type "$ext_name".rmfile &> /dev/null; then
+ "$ext_name".rmfile "$tifm_file_name"
+ fi
+ done
+ ;;
+ *)
+ echo "Invalid type ([d]irectory/[f]ile)."
+ ;;
+ esac
+ ;;
+ P)
+ echo "Choose a file or folder to change the permission (leave blank to cancel)."
+ read -p "item:: " tifm_select
+ if [[ "$tifm_select" == "" ]]; then
+ echo "Cancelled."
+ return
+ fi
+ echo "Choose the arguments from 'chmod' to set as permission for the file or folder (leave blank to cancel). (Read the manual for chmod for more info)"
+ read -p "perm:: " tifm_perm
+ if [[ "$tifm_perm" == "" ]]; then
+ echo "Cancelled."
+ return
+ fi
+ chmod $tifm_perm $tifm_select
+ # for every extension, if it has a function called name.fperms, call it
+ for ext_name in "${tifm_extensions[@]}"; do
+ if type "$ext_name".fperms &> /dev/null; then
+ "$ext_name".fperms "$tifm_select" "$tifm_perm"
+ fi
+ done
+ ;;
+ t)
+ /bin/bash
+ ;;
+ ";")
+ read -n 1 tifm_sub
+ echo ""
+ case "$tifm_sub" in
+ c)
+ # open config
+ $__TIFM_EDITOR "$SCRIPT_DIR/config.sh"
+ # reload config
+ source "$SCRIPT_DIR/config.sh"
+ ;;
+ e)
+ # open extension menu
+ local all_extensions=()
+ for extension in "$SCRIPT_DIR/extensions/"*".sh"; do
+ local ext_name=$(basename "$extension" .sh)
+ # if the extension name is in the extension_ignore file, ignore it
+ all_extensions+=("$ext_name")
+ done
+ display_extensions() {
+ clear
+ # display all extensions
+ echo "Extensions:"
+ for extension in "${all_extensions[@]}"; do
+ # if not in the ignored extensions list, display with a green checkmark
+ local grepped=$(grep "$extension" "$SCRIPT_DIR/extension_ignore")
+ if [[ -z "$grepped" ]]; then
+ echo -e " $GREEN✔$NORMAL $extension"
+ else
+ echo -e " $RED✘$NORMAL $extension"
+ fi
+ done
+ }
+ local executing=true
+ while $executing; do
+ display_extensions
+ echo ""
+ echo "type the name of an extension to toggle it, or type 'q' to quit."
+ read -p "extension:: " tifm_extension
+ if [[ "$tifm_extension" == "q" ]]; then
+ executing=false
+ continue
+ fi
+ # if the extension is ignored, unignore it
+ if [[ -n $(grep "$tifm_extension" "$SCRIPT_DIR/extension_ignore") ]]; then
+ sed -i "/$tifm_extension/d" "$SCRIPT_DIR/extension_ignore"
+ # remove from the ignored extensions list
+ local index=0
+ for ext in "${ignored_extensions[@]}"; do
+ if [[ "$ext" == "$tifm_extension" ]]; then
+ unset ignored_extensions[$index]
+ fi
+ ((index++))
+ done
+ else
+ # if the extension is not ignored, ignore it
+ echo "$tifm_extension" >> "$SCRIPT_DIR/extension_ignore"
+ fi
+ done
+ ;;
+ *)
+ echo "Invalid subcommand."
+ ;;
+ esac
+ ;;
+ "?")
+ echo "${LIME_YELLOW}List of native commands:$NORMAL
+N - Goes to a folder
+o - Opens a file
+p - View file (uses 'less' by default - change in config.sh)
+e - edit a file (uses 'nano' by default - change in config.sh)
+m - Moves/Renames a file
+c - Copies a file to a location
+i - Inspects a directory (ls -l) and pipes it to the selected pager ('less' by default - change in config.sh)
+n(f/d) - Creates a file or directory
+r(f/d) - Removes a file or directory
+P - Sets permissions for a specific file or folder
+t - Switches to command line mode, run 'exit' to exit.
+;(c/e) - Open [c]onfig file, [e]xtension menu
+Q - Quits the program"
+ if [[ ! -z "${tifm_extensions[@]}" ]]; then
+ echo "${LIME_YELLOW}List of commands defined by extensions [${tifm_extensions[@]}]:$NORMAL"
+ for cmd in "${tifm_extensions_commands_list[@]}"; do
+ echo "$cmd - ${tifm_extensions_commands_help[$cmd]}"
+ done
+ fi
+ ;;
+ Q)
+ clear
+ exit
+ ;;
+ "")
+ # do nothing
+ ;;
+ *)
+ if [[ ! -z "${tifm_extensions_commands[$ans]}" ]]; then
+ eval "${tifm_extensions_commands[$ans]}"
+ elif [[ "${tifm_extensions_longcommands[*]}" =~ "$ans" ]]; then
+ read -n 1 tifm_subcommand
+ echo ""
+ if [[ ! -z "${tifm_extensions_subcommands[$ans$tifm_subcommand]}" ]]; then
+ eval "${tifm_extensions_subcommands[$ans$tifm_subcommand]}"
+ else
+ echo "Invalid subcommand."
+ fi
+ else
+ echo "Unrecognized command. Type '?' for a list of commands."
+ fi
+ ;;
+ esac
+ STATUS=$?
}
-main
+(
+ clear
+ init
+ echo "$__TIFM_DECO_COLOUR$__ANGLE_UP_RIGHT$GREEN tifm $__TIFM_VERSION$NORMAL
+$__TIFM_DECO_COLOUR$__VBAR$NORMAL $BLUE${UNDERLINE}https://github.com/Rexxt/tifm$NORMAL
+$__TIFM_DECO_COLOUR$__VBAR$NORMAL $RED$REVERSE/!\\ you are running a bleeding edge version of tifm. $NORMAL
+$__TIFM_DECO_COLOUR$__VBAR$NORMAL $RED$REVERSE if you encounter any bugs, report them on github.$NORMAL
+$__TIFM_DECO_COLOUR$__ANGLE_DOWN_RIGHT$NORMAL strike '?' for help"
+ echo ""
+ while true; do
+ main
+ if "$__TIFM_CONFIRM_RETURN"; then
+ # wait for user to agree to return to the file view
+ echo
+ echo "${BRIGHT}${RED}press q to return to file view${NORMAL}"
+ key=""
+ while [ ! "$key" == "q" ]; do
+ read -n 1 key
+ done
+ clear
+ else
+ echo
+ fi
+ done
+)