gokcehan/lf

Plugin contributions?

Closed this issue ยท 25 comments

Can we contribute bash-based plugins for lf somewhere? I've created a really nice plugin to handle single or multiple file/folder compression that integrates well with lf.

#!/bin/bash

# Function to handle creating different types of archives
clear;
create_archive() {
    local archive_type=$1
    local archive_name=$2
    shift 2  # Remove first two arguments (type and name), leaving only the list of files

    case $archive_type in
        "tarx")
            mkdir "$archive_name"
            cp -r "$@" "$archive_name"
            tar -Jcvf "$archive_name.tar.xz" "$archive_name"
            rm -rf "$archive_name"
			echo " "
            echo "Compression successful! Archive created: $archive_name.tar.xz"
            ;;
        "targ")
            mkdir "$archive_name"
            cp -r "$@" "$archive_name"
            tar -czf "$archive_name.tar.gz" "$archive_name"
            rm -rf "$archive_name"
			echo " "
            echo "Compression successful! Archive created: $archive_name.tar.gz"
            ;;
        "tarz")
            mkdir "$archive_name"
            cp -r "$@" "$archive_name"
            env ZSTD="-6" tar --zstd -cf "$archive_name.tar.zst" "$archive_name"
            rm -rf "$archive_name"
			echo " "
            echo "Compression successful! Archive created: $archive_name.tar.zst"
            ;;
        "7zip")
            mkdir "$archive_name"
            cp -r "$@" "$archive_name"
            7z a "$archive_name.7z" "$archive_name"
            rm -rf "$archive_name"
			echo ""
            echo "Compression successful! Archive created: $archive_name.7z"
            ;;
        "zip")
            mkdir "$archive_name"
            cp -r "$@" "$archive_name"
            zip -r "$archive_name.zip" "$archive_name"
            rm -rf "$archive_name"
			echo " "
            echo "Compression successful! Archive created: $archive_name.zip"
            ;;
        *)	
            echo " "
            echo "Invalid archive type."
            echo " "
            read -p "Press Enter to continue..."
            ;;
    esac
}

# Main script
echo "Choose an archive type for selected file(s):"
echo "1. tarx (tar.xz)"
echo "2. targ (tar.gz)"
echo "3. tarz (tar.zst)"
echo "4. 7zip (.7z)"
echo "5. zip (.zip)"
read -p "Enter your choice (1-5): " choice

case $choice in
    1)
        read -p "Enter the name for the tar.xz archive: " archive_name
        if [[ "$archive_name" == "$(basename "$(realpath "$1")")" ]]; then
			echo " "
            echo "Error: Archive name cannot be the same as the directory name."
            exit 1
        fi
        create_archive "tarx" "$archive_name" "$@"
        ;;
    2)
        read -p "Enter the name for the tar.gz archive: " archive_name
        if [[ "$archive_name" == "$(basename "$(realpath "$1")")" ]]; then
			echo " "
            echo "Error: Archive name cannot be the same as the directory name."
            exit 1
        fi
        create_archive "targ" "$archive_name" "$@"
        ;;
    3)
        read -p "Enter the name for the tar.zst archive: " archive_name
        if [[ "$archive_name" == "$(basename "$(realpath "$1")")" ]]; then
			echo " "
            echo "Error: Archive name cannot be the same as the directory name."
            exit 1
        fi
        create_archive "tarz" "$archive_name" "$@"
        ;;
    4)
        read -p "Enter the name for the .7z archive: " archive_name
        if [[ "$archive_name" == "$(basename "$(realpath "$1")")" ]]; then
			echo " "
            echo "Error: Archive name cannot be the same as the directory name."
            exit 1
        fi
        create_archive "7zip" "$archive_name" "$@"
        ;;
    5)
        read -p "Enter the name for the .zip archive: " archive_name
        if [[ "$archive_name" == "$(basename "$(realpath "$1")")" ]]; then
			echo " "
            echo "Error: Archive name cannot be the same as the directory name."
            exit 1
        fi
        create_archive "zip" "$archive_name" "$@"
        ;;
    *)
    	echo " "
        echo "Invalid choice. Exiting..."
        echo " "
        read -p "Press Enter to continue..."
        exit
        ;;
esac

echo " "
read -p "Press Enter to continue..."

As a user, I do not think this is the place for general purpose scripts. We have Integrations page and I think that is enough.

Furthermore, I would not like to use the script you posted since it does not look good at all to me because of all the code repetitions, bad indentations and because it first duplicates on drive the directory to be compressed.
This is a quick rewrite of it that I have not really tested but just to see how much of original one can be removed (almost 100 lines less):

#!/bin/bash

formats=(
"tarx (tar.xz)"
"targ (tar.gz)"
"tarz (tar.zst)"
"7zip (.7z)"
"zip (.zip)"
)

choice="$(printf '%s\n' "${formats[@]}" | fzf)" || exit 1
read -r type extension < <(awk -F '[()]' '{print $1,$2}' <<< "$choice")

read -p "Enter the name for the $extension archive: " archive_name
if [ -e "$archive_name$extension" ]; then
	echo " "
	echo "Error: File or directory $archive_name.$extension already exists."
	exit 1
fi

case $type in
	"tarx") tar -Jcvf "$archive_name.tar.xz" "$1" ;;
	"targ") tar -czf "$archive_name.tar.gz" "$1" ;;
	"tarz") env ZSTD="-6" tar --zstd -cf "$archive_name.tar.zst" "$1" ;;
	"7zip") 7z a "$archive_name.7z" "$1" ;;
	"zip") zip -r "$archive_name.zip" "$1" ;;
esac

echo "Compression successful! Archive created: $archive_name$extension"

good point!

btw your script works for basic cases, but problem with it is that you also archive all parent dirs with the target folder too.

btw your script works for basic cases, but problem with it is that you also archive all parent dirs with the target folder too.

You can probably cd at that place and after only use basename when compressing

Fix with that and some status validation at the end

#!/bin/bash

formats=(
"tarx (tar.xz)"
"targ (tar.gz)"
"tarz (tar.zst)"
"7zip (.7z)"
"zip (.zip)"
)

choice="$(printf '%s\n' "${formats[@]}" | fzf)" || exit 1
read -r type extension < <(awk -F '[()]' '{print $1,$2}' <<< "$choice")
read -p "Enter the name for the $extension archive: " archive_name
cd "$(realpath -f "$1")"

if [ -e "$archive_name$extension" ]; then
	echo " "
	echo "Error: File or directory $archive_name.$extension already exists."
	exit 1
fi

case $type in
	"tarx") tar -Jcvf "$archive_name.tar.xz" "$(basename "$1")" ;;
	"targ") tar -czf "$archive_name.tar.gz" "$(basename "$1")" ;;
	"tarz") env ZSTD="-6" tar --zstd -cf "$archive_name.tar.zst" "$(basename "$1")" ;;
	"7zip") 7z a "$archive_name.7z" "$(basename "$1")" ;;
	"zip") zip -r "$archive_name.zip" "$(basename "$1")" ;;
esac

[ $? -ne 0 ] && echo "Compression failed!" || echo "Compression successful! Archive created: $archive_name$extension"

excellent!!!

why don't you push it for integration?

why don't you push it for integration?

Like I said in my first post, I do not think general purpose scripts have place in a repository (or its documentation) like this.

fair enough

as a final touch i merged some of the logic from my script in order to both avoid archiving the parent dirs and to allow for archiving multiple files/folders, since you seem to be really good at writing code, could it get any better than this?:

#!/bin/bash

formats=(
"tarx (tar.xz)"
"targ (tar.gz)"
"tarz (tar.zst)"
"7zip (.7z)"
"zip (.zip)"
)

choice="$(printf '%s\n' "${formats[@]}" | fzf)" || exit 1
read -r type extension < <(awk -F '[()]' '{print $1,$2}' <<< "$choice")
read -p "Enter the name for the $extension archive: " archive_name
cd "$(realpath -f "$1")"

if [ -e "$archive_name$extension" ]; then
	echo " "
	echo "Error: File or directory $archive_name.$extension already exists."
	exit 1
fi

case $type in
		"tarx")
	            mkdir "$archive_name"
	            cp -r "$@" "$archive_name"
	            tar -Jcvf "$archive_name.tar.xz" "$archive_name"
	            rm -rf "$archive_name"
	            ;;
	        "targ")
	            mkdir "$archive_name"
	            cp -r "$@" "$archive_name"
	            tar -czf "$archive_name.tar.gz" "$archive_name"
	            rm -rf "$archive_name"
	            ;;
	        "tarz")
	            mkdir "$archive_name"
	            cp -r "$@" "$archive_name"
	            env ZSTD="-6" tar --zstd -cf "$archive_name.tar.zst" "$archive_name"
	            rm -rf "$archive_name"
	            ;;
	        "7zip")
	            mkdir "$archive_name"
	            cp -r "$@" "$archive_name"
	            7z a "$archive_name.7z" "$archive_name"
	            rm -rf "$archive_name"
	            ;;
	        "zip")
	            mkdir "$archive_name"
	            cp -r "$@" "$archive_name"
	            zip -r "$archive_name.zip" "$archive_name"
	            rm -rf "$archive_name"
	            ;;
esac

[ $? -ne 0 ] && echo "Compression failed!" || echo "Compression successful! Archive created: $archive_name$extension"

could it get any better than this?

Maybe with some debugging on my side, but here is some small cleanup that should work the same as your version:

#!/bin/bash

formats=(
"tarx (tar.xz)"
"targ (tar.gz)"
"tarz (tar.zst)"
"7zip (.7z)"
"zip (.zip)"
)

choice="$(printf '%s\n' "${formats[@]}" | fzf)" || exit 1
read -r type extension < <(awk -F '[()]' '{print $1,$2}' <<< "$choice")
read -p "Enter the name for the $extension archive: " archive_name
cd "$(realpath -f "$1")"

if [ -e "$archive_name$extension" ]; then
	echo " "
	echo "Error: File or directory $archive_name.$extension already exists."
	exit 1
fi

mkdir "$archive_name"
cp -r "$@" "$archive_name"
case $type in
	"tarx") tar -Jcvf "$archive_name.tar.xz" "$archive_name" ;;
	"targ") tar -czf "$archive_name.tar.gz" "$archive_name" ;;
	"tarz") env ZSTD="-6" tar --zstd -cf "$archive_name.tar.zst" "$archive_name" ;;
	"7zip") 7z a "$archive_name.7z" "$archive_name" ;;
	"zip") zip -r "$archive_name.zip" "$archive_name";;
esac
[ $? -ne 0 ] && echo "Compression failed!" || echo "Compression successful! Archive created: $archive_name$extension"
rm -rf "$archive_name"

amazing! <3

amazing! <3

I'm glad it works. I might actually take this for myself as well and include it into my dotfiles repo.

It is really good. Having to call commands for compression with : from lf shell was such a pain.

@siyia2 I have pushed it with some small changes. It now copies to the temp directory for greater speed and less SSD usage, and now it archives without any parent directories.
Not sure if that is still matching your requirements, but you can maybe use something from it. Note that some functions (prompt and getfilename) are sourced from another file, so you would not we able to run the script without that file.

my /tmp is a small ramdisk 2gb and i do not intend to enlarge it, will it cause issues if i try to compress files larger than 2gb?

It probably would be a issue. You should probably skip that part then

Oh well it is ok, it probably does not meed my requirements, either way i mostly compress files on my large HDD. Rarely do i compress files on my SSD.

Are you the dmenu creator?

No. I just maintain a fork with some changes I need. Same for several other suckless tools

I see, asking because you code really clean, my original script looks bloated compared to your modification, almost like 1/3 of the original lines.

maybe a more generic version that creates the tmp dir directly in ram?:

#!/bin/bash

clear

formats=(
    "tarx (tar.xz)"
    "targ (tar.gz)"
    "tarz (tar.zst)"
    "7zip (.7z)"
    "zip (.zip)"
)

echo "Choose the archive format:"

for i in "${!formats[@]}"; do
    printf "%d) %s\n" "$((i + 1))" "${formats[$i]}"
done

echo " "

read -rp "Enter your choice (1-${#formats[@]}) or any other key to exit: " choice

echo " "

if [[ "$choice" =~ ^[1-${#formats[@]}]$ ]]; then
    choice=$((choice - 1))
    type="${formats[$choice]%% (*}"
    extension=".${formats[$choice]##* (}"
else
    echo "Exiting script."
    exit 0
fi

read -rp "Enter the name for the $extension archive: " archive_name

echo " "

if [ -e "$archive_name$extension" ]; then
    echo " "
    echo "Error: File or directory $archive_name.$extension already exists."
    exit 1
fi

# Create a temporary directory in RAM
temp_dir=$(mktemp -d /dev/shm/tmp.XXXXXXXXXX)

# Copy the files to the temporary directory
cp -r "$@" "$temp_dir"

case $type in
    "tarx") tar -Jcvf "$archive_name.tar.xz" -C "$temp_dir" . ;;
    "targ") tar -czf "$archive_name.tar.gz" -C "$temp_dir" . ;;
    "tarz") env ZSTD="-6" tar --zstd -cf "$archive_name.tar.zst" -C "$temp_dir" . ;;
    "7zip") 7z a "$archive_name.7z" "$temp_dir/*" ;;
    "zip") zip -r "$archive_name.zip" "$temp_dir/*" ;;
esac

echo " "

if [ $? -ne 0 ]; then
    echo "Compression failed!"
else
    echo "Compression successful! Archive created: $archive_name$extension"
fi

# Clean up the temporary directory
rm -rf "$temp_dir"

echo " "

read -rp "Press Enter to exit..."

Seems safer size wise and if RAM is full it can also use swap space.

Also a really useful tweak that works after extraction to automatically refresh working directory in lf, otherwise extracted files are not displayed initially:

cmd extract ${{
    set -f
    case $f in
        *.tar.bz|*.tar.bz2|*.tbz|*.tbz2)
            tar xjvf $f && lf -remote "send $id :reload" ;;
        *.tar.gz|*.tgz)
            tar xzvf $f && lf -remote "send $id :reload" ;;
        *.tar.xz|*.txz)
            tar xJvf $f && lf -remote "send $id :reload" ;;
        *.tar.zst|*.tzst)
            tar -xvf $f && lf -remote "send $id :reload" ;;
        *.zip)
            unzip $f && lf -remote "send $id :reload" ;;
        *.rar)
            unrar x $f && lf -remote "send $id :reload" ;;
        *.7z)
            7z x $f && lf -remote "send $id :reload" ;;
    esac
}}

That looks ok, but I would write it a bit differently:

cmd extract ${{
	set -f
	case $f in
		*.tar.bz|*.tar.bz2|*.tbz|*.tbz2) tar xjvf "$f" ;;
		*.tar.gz|*.tgz) tar xzvf "$f" ;;
		*.tar.xz|*.txz) tar xJvf "$f" ;;
		*.tar.zst|*.tzst) tar -xvf "$f" ;;
		*.zip) unzip "$f" ;;
		*.rar) unrar x "$f" ;;
		*.7z) 7z x "$f" ;;
		*) notify-send "Failed to extract '$f'..." ;;
	esac
	[ $? -eq 0 ] && lf -remote "send $id :reload"
}}

I have stolen a script from LukeSmithxyz and I use that for extracting

Yeah it seems more efficient

Also if you are interested i modified the extraction script slightly in order for it to work with multiple selected archives if more than one are available:

cmd extract ${{

	for f in $fx; do
	case $f in
		*.tar.bz|*.tar.bz2|*.tbz|*.tbz2) tar xjvf "$f" ;;
		*.tar.gz|*.tgz) tar xzvf "$f" ;;
		*.tar.xz|*.txz) tar xJvf "$f" ;;
		*.tar.zst|*.tzst) tar -xvf "$f" ;;
		*.zip) unzip "$f" ;;
		*.rar) unrar x "$f" ;;
		*.7z) 7z x "$f" ;;
		*) echo -e "Failed to extract '$f'..." ;;
	esac
	[ $? -eq 0 ] && lf -remote "send $id :reload"
done

}}