Complete overhaul of how daisy core tools are called, as well as changes to the help system
This commit is contained in:
parent
74ed7582f9
commit
3fa3daacba
9 changed files with 1263 additions and 682 deletions
486
README.md
486
README.md
|
|
@ -17,211 +17,287 @@ At first use, `lackadaisical` will provide you with information via `daisy_help`
|
|||
|
||||
## Getting started
|
||||
```
|
||||
--- BEGIN OF DAISY HELP ---
|
||||
===============================================================================
|
||||
Thanks for installing LACKADAISICAL!
|
||||
This project aims to provide useful utilities as well as learning material.
|
||||
|
||||
It is still under heavy development, not all of the things on this
|
||||
list are present/implemented. Utils marked with * are incomplete.
|
||||
|
||||
This suite provides a number of functions, aliases and scripts.
|
||||
They are all aimed at enhancing your efficiency.
|
||||
|
||||
To uninstall LACKADAISICAL, simply remove the source line from your
|
||||
shell RC, and reload it. This does not remove the files!
|
||||
You will also need to manually clear the configuration data in '<home>/.config/
|
||||
lackadaisical` if you so desire.
|
||||
|
||||
To read this notice again, call the function 'daisy_help'.
|
||||
<!-- --- BEGIN OF DAISY HELP --- -->
|
||||
===============================================================================
|
||||
These are the included binaries and utilities:
|
||||
- cdz:
|
||||
This utility extracts an archive to /tmp and changes
|
||||
directory to it in a new shell instance. Upon exit,
|
||||
the files are wiped. If `archivemount` is present,
|
||||
it will be used to mount the archive instead! You can
|
||||
bypass this behavior by specifying an env value of;
|
||||
NO_ARCHIVEMOUNT=1. The standard script supports zip,
|
||||
tarballs, and rar archives. We recommend relying on
|
||||
archivemount` if you have it installed.
|
||||
Use "--check" to only check if a file is an archive.
|
||||
It returns 0 if it is, 1 otherwise.
|
||||
- squasher:
|
||||
These convenient set of tools allow you to easily create
|
||||
XZ-compressed SquashFS images from existing folders to save
|
||||
disk space. The resulting folder is still writable since it is
|
||||
mounted using an 'overlay' system. You can use 'squasher make'
|
||||
to compresses an existing folder. These folders are automatically
|
||||
mounted when you use 'cd' to navigate to them (via an alias).
|
||||
When using 'make-squash-image' on an already mounted folder, it will
|
||||
instead update the existing image. As of writing, we do not have a
|
||||
SystemD service to auto-mount, however, you cam easily add auto-mount
|
||||
as a cron job. Here is a list of tools, they all take the same
|
||||
folder argument:
|
||||
> squasher make: Converts the folder into a hidden image
|
||||
on the same disk as the folder.
|
||||
> squasher mount: Sets up a mount for the XZ image alongside
|
||||
directories for changes
|
||||
> squasher umount: Self-explanatory.
|
||||
> squasher destroy: Extracts the image and essentially reverts
|
||||
everything. File changes are kept, however.
|
||||
- editx:
|
||||
Uses your standard CLI editor to create/modify a
|
||||
file and make it executable.
|
||||
- filewait:
|
||||
This tool is given a filename of a file that does
|
||||
not exist yet. When the file appears on disk, the
|
||||
tool quits and simply returns the filename. This
|
||||
can be used in personal workflows to stall a longer
|
||||
command that relies on the existence of said file.
|
||||
- agenda:
|
||||
Sets up a folder that is backed by a date-based tree
|
||||
directory structure. Requires an argument for the name
|
||||
of the folder to generate. Generates a symlink in this
|
||||
name to a date sub-folder in a local '.daisy' folder.
|
||||
Format is <dir> -> .daisy/<dir>/<year>/<month>/<day>.
|
||||
Recommended to run via crontab - automatically cleans
|
||||
up empty folders.
|
||||
A symbolic link to the base of the folder's tree, ".tree",
|
||||
is created in the root of the specified directly.
|
||||
Can be used for everything you'd like to sort by date.
|
||||
For example; a diary, browser downloads, backups, code.
|
||||
- own:
|
||||
A simple utility. It's effectively an alias for
|
||||
"sudo chown -R user:user" on the target dir/file.
|
||||
Root permissions required!
|
||||
- sshp:
|
||||
This is a wrapper for `ssh`, the meaning of the 'p' is "Plus".
|
||||
Integrates SSHFS support. If both client and host have SSHFS,
|
||||
this wrapper can be used to connect their file systems.
|
||||
For example, if you need to move files from one machine to
|
||||
another, you could do something like this:
|
||||
"sshp -m /:/mnt/pc -m /home/claire:/home/claire claire@pyon.net"
|
||||
If privilege escalation is necessary for FS access, you will
|
||||
be asked for a password.
|
||||
- shrc:
|
||||
This tool allows you to edit the RC file for your
|
||||
shell in your preferred editor. After saving, the
|
||||
file is sourced by your shell if modified.
|
||||
- sw:
|
||||
A basic function that swaps two files by content.
|
||||
Useful for restoring backups.
|
||||
- what:
|
||||
This is a tool similar to which and others, the key
|
||||
difference is that it returns partial matches. It can
|
||||
be used to search for binaries.
|
||||
- scripbox:
|
||||
This tool can be used to pack bash scripts into one
|
||||
big megascript, much like how `busybox` works.
|
||||
You can also make symlinks to it to invoke a specific
|
||||
script.
|
||||
- bak/unbak:
|
||||
These small utilities make backups of files by making
|
||||
a copy with a .bak suffix. Unbak reverses the process
|
||||
by using sw and removes the backup.
|
||||
- lsa:
|
||||
A simple alias for `ls -lah`.
|
||||
- lsn:
|
||||
A simple alias for `ls -lah --sort=time --reverse`.
|
||||
- lss:
|
||||
A simple alias for `ls -lah --sort=size --reverse`.
|
||||
- editbin:
|
||||
An alias for `editx $\(which <x>\)`. Saves on typing.
|
||||
- editpeco:
|
||||
This function uses peco+tree like `cdp`, but opens
|
||||
your editor on the selected file(s). After you exit
|
||||
your editor(s), you are returned to peco where you left
|
||||
off.
|
||||
- ched:
|
||||
Like chsh but for your editor (EDITOR env). A list
|
||||
from which you can choose an installed editor
|
||||
(CLI or GUI) is shown. This list is by no means complete.
|
||||
The editor for LACKADAISICAL and the global editor are
|
||||
separate. If the EDITOR variable is already defined,
|
||||
only LD_EDITOR will be changed. LD_EDITOR is the editor
|
||||
used by LACKADAISICAL utilities.
|
||||
To override the global EDITOR variable, pass "-g".
|
||||
To restore the normal behavior of checking for an earlier
|
||||
definition of EDITOR after passing "-g", run `ched` without
|
||||
arguments.
|
||||
- cdf:
|
||||
Use fzf to find a file and then cd to its location.
|
||||
- cdp:
|
||||
Similar to `cdf` but uses tree+peco for the query.
|
||||
- clip:
|
||||
An extremely simple utility that functions as a clipboard of sorts.
|
||||
To set the variable, run "clip <data>" or provide data via stdin.
|
||||
To get the variable, simply run clip without any arguments.
|
||||
The variable is stored locally in the shell as "LD_CLIP".
|
||||
- ldrc:
|
||||
Edits daisy.source and re-sources it, similarly to shrc.
|
||||
Append "-e" to edit "extra.src", to add custom functions in the
|
||||
lackadaisical namespace.
|
||||
- daisy_reload:
|
||||
Re-sources daisy.source. Essentially `ldrc` without
|
||||
editing.
|
||||
- grab:
|
||||
Alias for `awk '{print $x}'`, where x is a number.
|
||||
E.g. `echo 'a b c' | grab 2` returns 'b'.
|
||||
- daisy_cbin:
|
||||
Contains the name of the current LACKADAISICAL
|
||||
binary being run.
|
||||
- daisy_enc:
|
||||
Converts a file/stdin to a base64 block that can be
|
||||
decoded by passing the output(s) to `daisy_dec`.
|
||||
The output of `daisy_enc` can be concatenated with the
|
||||
output of another encoded file to create a multi-file
|
||||
base64 archive similar to `daisy_enc_multi`.
|
||||
Does not support symlinks yet, and will instead treat it
|
||||
as a full input file (reads the data of the linked file).
|
||||
When using stdin, please provide a filename as argument.
|
||||
- daisy_enc_multi:
|
||||
A version of `daisy_enc` that encodes multiple
|
||||
files and outputs `daisy_base64_data` blocks to a file
|
||||
or stdout. These outputs can be concatenated as well.
|
||||
- daisy_dec:
|
||||
Converts `daisy_base64_data` blocks back to the form
|
||||
it was in originally.
|
||||
- daisy_dec_multi:
|
||||
A version of daisy_dec that runs on multiple input
|
||||
blocks that are either stored in a file or stdin.
|
||||
- daisy_alias:
|
||||
This utility sets persistent user aliases stored in
|
||||
"~/.config/lackadaisical/aliases.src".
|
||||
They will remain persistent until unaliased with
|
||||
daisy_unalias.
|
||||
Call daisy_alias using '' instead of "".
|
||||
E.g. `daisy_alias hello='echo "Hello!"' - instead of
|
||||
`daisy_alias hello="echo \"Hello!\"".
|
||||
This prevents an early invocation of possible nested
|
||||
aliases.
|
||||
Call this function without arguments to get a list of
|
||||
registered aliases as well as indices for easy unaliasing
|
||||
using `daisy_unalias`.
|
||||
- daisy_unalias:
|
||||
This utility removes an alias from those registered with
|
||||
daisy_alias. It accepts either an alias name, or an index
|
||||
given by calling `daisy_alias` without arguments.
|
||||
In case of a mistake, a backup is made under the filename
|
||||
"~/.config/lackadaisical/aliases.src.bak".
|
||||
To restore this file, you can use these commands:
|
||||
`unbak ~/.config/lackadaisical/aliases.src'
|
||||
`daisy_reload`
|
||||
- daisy_list:
|
||||
List all available commands without description.
|
||||
- daisy_clear:
|
||||
Removes all configuration, including aliases.
|
||||
A backup is made and can be restored using "daisy_restore".
|
||||
Triggers a reload.
|
||||
- daisy_backup:
|
||||
Backs up all config files. These can be restored using
|
||||
"daisy_restore".
|
||||
- daisy_restore:
|
||||
Undoes "daisy_clear" by restoring config files.
|
||||
Triggers a reload.
|
||||
- ld_*:
|
||||
All functions prefixed by "daisy_" are also available with
|
||||
the prefix "ld_" via aliases provided in daisy.source.
|
||||
--- END OF DAISY HELP ---
|
||||
················································································
|
||||
< cdz >
|
||||
················································································
|
||||
This utility extracts an archive to /tmp and changes directory to it in a new
|
||||
shell instance. Upon exit, the files are wiped. If `archivemount` is present,
|
||||
it will be used to mount the archive instead! You can bypass this behavior by
|
||||
specifying an env value of; NO_ARCHIVEMOUNT=1. The standard script supports
|
||||
zip, tarballs, and rar archives. We recommend relying on archivemount` if you
|
||||
have it installed. Use "--check" to only check if a file is an archive. It
|
||||
returns 0 if it is, 1 otherwise.
|
||||
················································································
|
||||
|
||||
< squasher >
|
||||
················································································
|
||||
These convenient set of tools allow you to easily create XZ-compressed SquashFS
|
||||
images from existing folders to save disk space. The resulting folder is still
|
||||
writable since it is mounted using an 'overlay' system. You can use 'squasher
|
||||
make' to compresses an existing folder. These folders are automatically mounted
|
||||
when you use 'cd' to navigate to them (via the 'multicd' alias). When using
|
||||
'make-squash-image' on an already mounted folder, it will update the existing
|
||||
image. As of writing, we do not have a SystemD service to auto-mount, however,
|
||||
you cam easily add auto-mount as a cron job. Here is a list of tools, they all
|
||||
take the same folder argument:
|
||||
- squasher make: Converts the folder into an image on the same disk as the
|
||||
folder.
|
||||
- squasher mount: Sets up a mount for the XZ image alongside
|
||||
OverlayFS for changes.
|
||||
- squasher umount: Fully unmounts the image and overlay filesystem.
|
||||
- squasher destroy: Extracts the image and essentially reverts everything.
|
||||
All file changes are kept and applied to the unextracted
|
||||
data.
|
||||
················································································
|
||||
|
||||
< editx >
|
||||
················································································
|
||||
Uses your standard CLI editor to create/modify a file and make it executable.
|
||||
················································································
|
||||
|
||||
< filewait >
|
||||
················································································
|
||||
This tool is given a filename of a file that does not exist yet. When the file
|
||||
appears on disk, the tool quits and simply returns the filename. This can be
|
||||
used in personal workflows to stall a longer command that relies on the
|
||||
existence of said file.
|
||||
················································································
|
||||
|
||||
< agenda >
|
||||
················································································
|
||||
Sets up a folder that is backed by a date-based tree directory structure.
|
||||
Requires an argument for the name of the folder to generate. Generates a
|
||||
symlink in this name to a date sub-folder in a local '.daisy' folder. Format is
|
||||
<dir> -> .daisy/<dir>/<year>/<month>/<day>. Recommended to run via crontab -
|
||||
automatically cleans up empty folders. A symbolic link to the base of the
|
||||
folder's tree, ".tree", is created in the root of the specified directly. Can
|
||||
be used for everything you'd like to sort by date. For example; a diary,
|
||||
browser downloads, backups, code.
|
||||
················································································
|
||||
|
||||
< own >
|
||||
················································································
|
||||
A simple utility. It's effectively an alias for "sudo chown -R user:user" on
|
||||
the target dir/file. Root permissions required!
|
||||
················································································
|
||||
|
||||
< sshp >
|
||||
················································································
|
||||
This is a wrapper for `ssh`, the meaning of the 'p' is "Plus". Integrates SSHFS
|
||||
support. If both client and host have SSHFS, this wrapper can be used to
|
||||
connect their file systems. For example, if you need to move files from one
|
||||
machine to another, you could do something like this: "sshp -m /:/mnt/pc -m
|
||||
/home/claire:/home/claire claire@pyon.net" If privilege escalation is necessary
|
||||
for FS access, you will be asked for a password.
|
||||
················································································
|
||||
|
||||
< shrc >
|
||||
················································································
|
||||
This tool allows you to edit the RC file for your shell in your preferred
|
||||
editor. After saving, the file is sourced by your shell if modified.
|
||||
················································································
|
||||
|
||||
< sw >
|
||||
················································································
|
||||
A basic function that swaps two files by content. Useful for restoring backups.
|
||||
················································································
|
||||
|
||||
< what >
|
||||
················································································
|
||||
This is a tool similar to which and others, the key difference is that it
|
||||
returns partial matches. It can be used to search for binaries.
|
||||
················································································
|
||||
|
||||
< scriptbox >
|
||||
················································································
|
||||
This tool can be used to pack bash scripts into one big megascript, much like
|
||||
how `busybox` works. You can also make symlinks to it to invoke a specific
|
||||
script.
|
||||
················································································
|
||||
|
||||
< bak/unbak >
|
||||
················································································
|
||||
These small utilities make backups of files by making a copy with a .bak
|
||||
suffix. Unbak reverses the process by using sw and removes the backup.
|
||||
················································································
|
||||
|
||||
< lsa >
|
||||
················································································
|
||||
A simple alias for `ls -lah`.
|
||||
················································································
|
||||
|
||||
< lsn >
|
||||
················································································
|
||||
A simple alias for `ls -lah --sort=time --reverse`.
|
||||
················································································
|
||||
|
||||
< lss >
|
||||
················································································
|
||||
A simple alias for `ls -lah --sort=size --reverse`.
|
||||
················································································
|
||||
|
||||
< editbin >
|
||||
················································································
|
||||
An alias for `editx $\(which <x>\)`. Saves on typing.
|
||||
················································································
|
||||
|
||||
< editpeco >
|
||||
················································································
|
||||
This function uses peco+tree like `cdp`, but opens your editor on the selected
|
||||
file(s). After you exit your editor(s), you are returned to peco where you left
|
||||
off.
|
||||
················································································
|
||||
|
||||
< ched >
|
||||
················································································
|
||||
Like chsh but for your editor (EDITOR env). A list from which you can choose an
|
||||
installed editor (CLI or GUI) is shown. This list is by no means complete. The
|
||||
editor for LACKADAISICAL and the global editor are separate. If the EDITOR
|
||||
variable is already defined, only LD_EDITOR will be changed. LD_EDITOR is the
|
||||
editor used by LACKADAISICAL utilities. To override the global EDITOR variable,
|
||||
pass "-g". To restore the normal behavior of checking for an earlier definition
|
||||
of EDITOR after passing "-g", run `ched` without arguments.
|
||||
················································································
|
||||
|
||||
< cdf >
|
||||
················································································
|
||||
Use fzf to find a file and then cd to its location.
|
||||
················································································
|
||||
|
||||
< cdp >
|
||||
················································································
|
||||
Similar to `cdf` but uses tree+peco for the query.
|
||||
················································································
|
||||
|
||||
< clip >
|
||||
················································································
|
||||
An extremely simple utility that functions as a clipboard of sorts. To set the
|
||||
variable, run "clip <data>" or provide data via stdin. To get the variable,
|
||||
simply run clip without any arguments. The variable is stored locally in the
|
||||
shell as "LD_CLIP".
|
||||
················································································
|
||||
|
||||
< ldrc >
|
||||
················································································
|
||||
Edits daisy.source and re-sources it, similarly to shrc. Append "-e" to edit
|
||||
"extra.src", to add custom functions in the lackadaisical namespace.
|
||||
················································································
|
||||
|
||||
< daisy reload >
|
||||
················································································
|
||||
Re-sources daisy.source. Essentially `ldrc` without editing.
|
||||
················································································
|
||||
|
||||
< grab >
|
||||
················································································
|
||||
Alias for `awk '{print $x}'`, where x is a number. E.g. `echo 'a b c' | grab 2`
|
||||
returns 'b'.
|
||||
················································································
|
||||
|
||||
< daisy cbin >
|
||||
················································································
|
||||
Contains the name of the current LACKADAISICAL binary being run.
|
||||
················································································
|
||||
|
||||
< daisy enc >
|
||||
················································································
|
||||
Converts a file/stdin to a base64 block that can be decoded by passing the
|
||||
output(s) to `daisy_dec`. The output of `daisy_enc` can be concatenated with
|
||||
the output of another encoded file to create a multi-file base64 archive
|
||||
similar to `daisy_enc_multi`. Does not support symlinks yet, and will instead
|
||||
treat it as a full input file (reads the data of the linked file). When using
|
||||
stdin, please provide a filename as argument.
|
||||
················································································
|
||||
|
||||
< daisy enc multi >
|
||||
················································································
|
||||
A version of `daisy_enc` that encodes multiple files and outputs
|
||||
`daisy_base64_data` blocks to a file or stdout. These outputs can be
|
||||
concatenated as well.
|
||||
················································································
|
||||
|
||||
< daisy enc folder >
|
||||
················································································
|
||||
A version of `daisy_enc` that encodes a whole folder into a series of
|
||||
`daisy_base64_data` blocks. Requires the `tree` utility.
|
||||
················································································
|
||||
|
||||
< daisy dec >
|
||||
················································································
|
||||
Converts `daisy_base64_data` blocks back to the form it was in originally.
|
||||
················································································
|
||||
|
||||
< daisy dec multi >
|
||||
················································································
|
||||
A version of daisy_dec that runs on multiple input blocks that are either
|
||||
stored in a file or stdin.
|
||||
················································································
|
||||
|
||||
< daisy alias >
|
||||
················································································
|
||||
This utility sets persistent user aliases stored in
|
||||
"~/.config/lackadaisical/aliases.src". They will remain persistent until
|
||||
unaliased with daisy_unalias. Call daisy_alias using '' instead of "". E.g.
|
||||
`daisy_alias hello='echo "Hello!"' - instead of `daisy_alias hello="echo
|
||||
\"Hello!\"". This prevents an early invocation of possible nested aliases. Call
|
||||
this function without arguments to get a list of registered aliases as well as
|
||||
indices for easy unaliasing using `daisy_unalias`.
|
||||
················································································
|
||||
|
||||
< daisy unalias >
|
||||
················································································
|
||||
This utility removes an alias from those registered with daisy_alias. It
|
||||
accepts either an alias name, or an index given by calling `daisy_alias`
|
||||
without arguments. In case of a mistake, a backup is made under the filename
|
||||
"~/.config/lackadaisical/aliases.src.bak". To restore this file, you can use
|
||||
these commands: `unbak ~/.config/lackadaisical/aliases.src' `daisy_reload`
|
||||
················································································
|
||||
|
||||
< daisy list >
|
||||
················································································
|
||||
List all available commands, utilities and tools - without description.
|
||||
················································································
|
||||
|
||||
< daisy clear >
|
||||
················································································
|
||||
Removes all configuration, including aliases. A backup is made and can be
|
||||
restored using "daisy_restore". Triggers a reload.
|
||||
················································································
|
||||
|
||||
< daisy backup >
|
||||
················································································
|
||||
Backs up all config files. These can be restored using "daisy_restore".
|
||||
················································································
|
||||
|
||||
< daisy restore >
|
||||
················································································
|
||||
Undoes "daisy_clear" by restoring config files. Triggers a reload.
|
||||
················································································
|
||||
|
||||
< daisy_* /ld_* >
|
||||
················································································
|
||||
All functions prefixed by "daisy" are also available as alias with the prefixes
|
||||
"daisy_" and "ld_".
|
||||
················································································
|
||||
|
||||
< daisy help >
|
||||
················································································
|
||||
Shows this exact interface for information about different utilities and
|
||||
functions provided by `lackadaisical`.
|
||||
- help <command|utility|tool>: Shows a help entry for a particular command,
|
||||
including allternative function names.
|
||||
- help Shows fully formatted help entries for every
|
||||
function listed by "daisy list" (recommended
|
||||
for first-time users).
|
||||
················································································
|
||||
|
||||
< daisy welcome >
|
||||
················································································
|
||||
Showws some basic post-installation information about LACKADAISICAL and how to
|
||||
use it.
|
||||
················································································
|
||||
<!-- --- END OF DAISY HELP --- -->
|
||||
```
|
||||
|
|
|
|||
48
check.sh
Executable file
48
check.sh
Executable file
|
|
@ -0,0 +1,48 @@
|
|||
#!/usr/bin/env bash
|
||||
# Lackadaisical Dependency Checker
|
||||
|
||||
echo "Checking dependencies for LACKADAISICAL..."
|
||||
echo "=========================================="
|
||||
|
||||
check_bin()
|
||||
{
|
||||
if [[ $1 ]];
|
||||
then echo -e "[ \e[32mOK\e[0m ] $1 ($2)"
|
||||
return 0
|
||||
else
|
||||
echo -e "[ \e[31m--\e[0m ] $1 ($2)"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
echo "--- Core (Essential) ---"
|
||||
check_bin bash "Shell environment"
|
||||
check_bin awk "Text processing"
|
||||
check_bin sed "Stream editing"
|
||||
check_bin grep "Pattern matching"
|
||||
check_bin base64 "Data encoding"
|
||||
check_bin realpath "Path resolution"
|
||||
|
||||
echo -e "\n--- Enhanced UI & Navigation ---"
|
||||
check_bin fzf "Used by cdf"
|
||||
check_bin peco "Used by cdp, editpeco"
|
||||
check_bin tree "Used by cdp, editpeco, daisy_enc_folder"
|
||||
check_bin dialog "Used by ched"
|
||||
|
||||
echo -e "\n--- Archives & Filesystems ---"
|
||||
check_bin archivemount "Used by cdz (mounting)"
|
||||
check_bin tar "Used by cdz (extraction)"
|
||||
check_bin unzip "Used by cdz (extraction)"
|
||||
check_bin unrar "Used by cdz (extraction)"
|
||||
check_bin mksquashfs "Used by squasher make"
|
||||
check_bin rsync "Used by squasher destroy"
|
||||
check_bin sshfs "Used by sshp"
|
||||
check_bin fusermount "Used by sshp, cdz"
|
||||
|
||||
echo -e "\n--- System ---"
|
||||
check_bin sudo "Privilege escalation"
|
||||
check_bin systemctl "Service management"
|
||||
check_bin perl "Advanced error reporting"
|
||||
|
||||
echo "=========================================="
|
||||
echo "Check complete."
|
||||
351
daisy
Executable file
351
daisy
Executable file
|
|
@ -0,0 +1,351 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# LACKADAISICAL CLI
|
||||
|
||||
# Environment Setup
|
||||
LD_CONFIG_FOLDER="${LD_CONFIG_FOLDER:-$HOME/.config/lackadaisical}"
|
||||
LD_ALIASFILE="${LD_ALIASFILE:-$LD_CONFIG_FOLDER/aliases.src}"
|
||||
LD_EDITORFILE="${LD_EDITORFILE:-$LD_CONFIG_FOLDER/editor.src}"
|
||||
LD_ESOURCEFILE="${LD_ESOURCEFILE:-$LD_CONFIG_FOLDER/extra.src}"
|
||||
|
||||
if [[ -z "$LD_FOLDER" ]]; then
|
||||
LD_FOLDER=$(dirname "$(realpath "$0")")
|
||||
fi
|
||||
|
||||
ld_dbg()
|
||||
{
|
||||
if [[ $_LD_DEBUG == 1 ]]; then
|
||||
echo "DEBUG: $*" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Internal Utils ---
|
||||
|
||||
_daisy_wait_for_editor()
|
||||
{
|
||||
local pname="$1"
|
||||
local fname="$2"
|
||||
sleep 1
|
||||
while true; do
|
||||
alive=$(pgrep -f "$pname.*$fname")
|
||||
if [[ $alive == "" ]]; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
_daisy_editor()
|
||||
{
|
||||
local editor=${LD_EDITOR:-$EDITOR}
|
||||
ld_dbg "Opening $editor to edit file: $1"
|
||||
$editor "$1"
|
||||
sleep 1
|
||||
_daisy_wait_for_editor "$editor" "$1"
|
||||
}
|
||||
|
||||
_daisy_enc()
|
||||
{
|
||||
local enc_is_folder="${ENC_IS_FOLDER:-0}"
|
||||
if [ -t 0 ] && [ -z "$1" ]; then
|
||||
echo "# $0: No arguments or stdin specified!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -t 0 ] && [ -z "$1" ]; then
|
||||
echo "# $0: Please provide a filename as argument when using stdin"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -n "$1" ] && [ -d "$1" ]; then
|
||||
echo -e "daisy_create_folder=$1"
|
||||
else
|
||||
local file_dir=""
|
||||
local file_name=""
|
||||
local perms=755
|
||||
local target=$1
|
||||
|
||||
if [[ ! -t 0 ]] && [[ $enc_is_folder == 0 ]]; then
|
||||
file_dir="."
|
||||
file_name="$1"
|
||||
elif [ -f "$1" ]; then
|
||||
file_dir=$(dirname "$1")
|
||||
file_name=$(basename "$1")
|
||||
perms=$(stat -c %a "$1")
|
||||
else
|
||||
echo "# $0: An error occured during encoding."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local base64_inner
|
||||
base64_inner=$(cat "${1:-/dev/stdin}" | base64 | tr -d '\n')
|
||||
echo -e "daisy_folder_$file_name=$file_dir"
|
||||
echo -e "daisy_data_base64_$file_name=\"$base64_inner\""
|
||||
echo -e "daisy_perms_$file_name=$perms"
|
||||
fi
|
||||
}
|
||||
|
||||
_daisy_dec()
|
||||
{
|
||||
if [ -t 0 ] && [ -z "$1" ]; then
|
||||
echo "$0: No arguments or stdin specified!"
|
||||
return 1
|
||||
fi
|
||||
local data
|
||||
data=$(cat "${1:-/dev/stdin}" | grep -v "#")
|
||||
echo -e "$data" | cut -d "=" -f 2- | cut -b 2- | head -c -2 | base64 -d
|
||||
}
|
||||
|
||||
_daisy_unalias()
|
||||
{
|
||||
local unalias_param="$1"
|
||||
if [[ $unalias_param =~ ^[0-9]+$ ]]; then
|
||||
unalias_param=$(head -"$unalias_param" "$LD_ALIASFILE" 2>/dev/null | tail -1 | cut -d "=" -f 1 | awk '{print $2}')
|
||||
fi
|
||||
if [[ -z "$unalias_param" ]]; then
|
||||
return
|
||||
fi
|
||||
if [[ -f "$LD_ALIASFILE" ]]; then
|
||||
local newdata
|
||||
newdata=$(grep -v "alias $unalias_param" "$LD_ALIASFILE" 2>/dev/null)
|
||||
cp "$LD_ALIASFILE" "$LD_ALIASFILE.bak" 2>/dev/null
|
||||
echo -e "$newdata" > "$LD_ALIASFILE"
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Command Functions ---
|
||||
|
||||
cmd_help()
|
||||
{
|
||||
local target_tool="$1"
|
||||
local file="$LD_FOLDER/README.md"
|
||||
if [[ ! -f "$file" ]]; then
|
||||
echo "README.md not found at $file"
|
||||
exit 1
|
||||
fi
|
||||
sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
|
||||
if [ -z "$target_tool" ]; then
|
||||
cat
|
||||
else
|
||||
awk -v query="$target_tool" '
|
||||
BEGIN { found=0; printing=0 }
|
||||
$0 ~ /^[[:space:]]*- / {
|
||||
printing=0
|
||||
sig = $0
|
||||
sub(/^[[:space:]]*- /, "", sig)
|
||||
sub(/:[[:space:]]*$/, "", sig)
|
||||
split(sig, names, "/")
|
||||
is_match = 0
|
||||
if (sig == query) is_match = 1
|
||||
else {
|
||||
for (i in names);
|
||||
do
|
||||
if (names[i] == query) { is_match = 1; break }
|
||||
done
|
||||
}
|
||||
if (is_match) {
|
||||
printing=1
|
||||
found=1
|
||||
print $0
|
||||
next
|
||||
}
|
||||
}
|
||||
printing {
|
||||
if ($0 ~ /^[[:space:]]*- /) { printing=0; next }
|
||||
print
|
||||
}
|
||||
END {
|
||||
if (found == 0) {
|
||||
print "Tool '\''" query "'\'' not found in README.md."
|
||||
}
|
||||
}
|
||||
'
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_list()
|
||||
{
|
||||
local file="$LD_FOLDER/README.md"
|
||||
if [[ ! -f "$file" ]]; then
|
||||
echo "README.md not found at $file"
|
||||
exit 1
|
||||
fi
|
||||
echo "Available LACKADAISICAL commands:"
|
||||
sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
|
||||
awk '
|
||||
/^[[:space:]]*- / {
|
||||
sub(/^[[:space:]]*- /, "");
|
||||
sub(/:[[:space:]]*$/, "");
|
||||
print " " $0
|
||||
}
|
||||
' | sort
|
||||
}
|
||||
|
||||
cmd_enc()
|
||||
{
|
||||
case "$1" in
|
||||
multi)
|
||||
shift
|
||||
for f in "$@"; do _daisy_enc "$f"; done
|
||||
;;
|
||||
folder)
|
||||
if ! command -v tree >/dev/null 2>&1; then
|
||||
echo "This function requires the utility 'tree'. Please install it."
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
local dir="$1"
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
echo "Directory not found: $dir"
|
||||
exit 1
|
||||
fi
|
||||
cd "$dir" || exit 1
|
||||
tree -fia --noreport . | sed 1d | while read -r item; do
|
||||
ENC_IS_FOLDER=1 _daisy_enc "$item"
|
||||
done
|
||||
;;
|
||||
*)
|
||||
_daisy_enc "$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
cmd_dec()
|
||||
{
|
||||
case "$1" in
|
||||
multi)
|
||||
shift
|
||||
local arg1=$1
|
||||
local arg2=$2
|
||||
if [ ! -t 0 ]; then
|
||||
arg2=$1
|
||||
arg1=/dev/stdin
|
||||
fi
|
||||
[[ -t 0 ]] && [[ ! -f "$arg1" ]] && echo "daisy dec multi: No input file specified" && exit 1
|
||||
[[ ! -d "$arg2" ]] && echo "daisy dec multi: No output directory specified" && exit 1
|
||||
|
||||
local folder=""
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == "daisy_create_folder="* ]]; then
|
||||
folder=$(echo "$line" | cut -d "=" -f 2)
|
||||
mkdir -p "$arg2/$folder"
|
||||
elif [[ "$line" == "daisy_folder"* ]]; then
|
||||
folder=$(echo "$line" | cut -d "=" -f 2)
|
||||
elif [[ "$line" == "daisy_data_base64"* ]]; then
|
||||
local file=$(echo "$line" | cut -d "_" -f 4- | cut -d "=" -f 1)
|
||||
mkdir -p "$arg2/$folder"
|
||||
_daisy_dec <(echo "$line") > "$arg2/$folder/$file"
|
||||
elif [[ "$line" == "daisy_perms"* ]]; then
|
||||
local file=$(echo "$line" | cut -d "_" -f 3- | cut -d "=" -f 1)
|
||||
local perms=$(echo "$line" | cut -d "_" -f 3- | cut -d "=" -f 2)
|
||||
chmod "$perms" "$arg2/$folder/$file"
|
||||
fi
|
||||
done < "$arg1"
|
||||
;;
|
||||
*)
|
||||
_daisy_dec "$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
cmd_alias()
|
||||
{
|
||||
local alias_param="$*"
|
||||
if [[ -z "$alias_param" ]]; then
|
||||
echo "Active lackadaisical alias lines:"
|
||||
local linenum=1
|
||||
if [[ -f "$LD_ALIASFILE" ]]; then
|
||||
while IFS= read -r line; do
|
||||
line=$(echo "$line" | sed 's/alias //g')
|
||||
echo "$linenum: $line"
|
||||
((linenum++))
|
||||
done < "$LD_ALIASFILE"
|
||||
fi
|
||||
else
|
||||
local alias_name=$(echo "$alias_param" | grep -o ".*=" | tr -d =)
|
||||
if [[ $alias_name =~ ^[0-9]+$ ]]; then
|
||||
echo "An alias cannot start with a number! Exiting."
|
||||
exit 1
|
||||
fi
|
||||
_daisy_unalias "$alias_name"
|
||||
echo "alias ${alias_param%=*}=\"${alias_param#*=}\"" >> "$LD_ALIASFILE"
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_clear()
|
||||
{
|
||||
find "$LD_CONFIG_FOLDER" -name "*.src" -type f | while read -r f; do
|
||||
cp -R "$f" "$f.bak"
|
||||
echo "Removing config file: $f"
|
||||
rm -rf "$f"
|
||||
done
|
||||
echo "Config cleared. Use 'daisy restore' if you would like to undo this."
|
||||
}
|
||||
|
||||
cmd_restore()
|
||||
{
|
||||
find "$LD_CONFIG_FOLDER" -name "*.src.bak" -type f | while read -r f; do
|
||||
local target="${f%.bak}"
|
||||
cp -R "$f" "$target"
|
||||
rm -rf "$f"
|
||||
echo "Restored backup: $target <-- $f"
|
||||
done
|
||||
echo "Config restored. Backups have been retained."
|
||||
}
|
||||
|
||||
cmd_combine()
|
||||
{
|
||||
local cmds=()
|
||||
local args=()
|
||||
local separator_found=false
|
||||
|
||||
for item in "$@"; do
|
||||
if [[ "$item" == "--" ]]; then
|
||||
separator_found=true
|
||||
continue
|
||||
fi
|
||||
|
||||
if $separator_found; then
|
||||
args+=("$item")
|
||||
else
|
||||
cmds+=("$item")
|
||||
fi
|
||||
done
|
||||
|
||||
for cmd in "${cmds[@]}"; do
|
||||
set -- "${args[@]}"
|
||||
eval "$cmd"
|
||||
done
|
||||
}
|
||||
|
||||
# --- Dispatcher ---
|
||||
|
||||
case "$1" in
|
||||
help) shift; cmd_help "$@" ;;
|
||||
list) shift; cmd_list "$@" ;;
|
||||
enc) shift; cmd_enc "$@" ;;
|
||||
dec) shift; cmd_dec "$@" ;;
|
||||
alias) shift; cmd_alias "$@" ;;
|
||||
unalias) shift; _daisy_unalias "$@" ;;
|
||||
backup) shift; find "$LD_CONFIG_FOLDER" -name "*.src" -type f | while read -r f; do cp -R "$f" "$f.bak"; echo "Backup made: $f --> $f.bak"; done ;;
|
||||
clear) shift; cmd_clear ;;
|
||||
restore) shift; cmd_restore ;;
|
||||
combine) shift; cmd_combine ;;
|
||||
editor) shift; _daisy_editor "$@" ;;
|
||||
wait)
|
||||
if [[ "$2" == "for" && "$3" == "editor" ]]; then
|
||||
shift 3
|
||||
_daisy_wait_for_editor "$@"
|
||||
else
|
||||
echo "Unknown daisy command: wait $*"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
reload)
|
||||
LD_INTERNAL=0 source "$LD_SOURCE_FILE"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown daisy command: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
424
daisy.command.source
Executable file
424
daisy.command.source
Executable file
|
|
@ -0,0 +1,424 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# LACKADAISICAL CLI
|
||||
|
||||
# Environment Setup
|
||||
LD_CONFIG_FOLDER="${LD_CONFIG_FOLDER:-$HOME/.config/lackadaisical}"
|
||||
LD_ALIASFILE="${LD_ALIASFILE:-$LD_CONFIG_FOLDER/aliases.src}"
|
||||
LD_EDITORFILE="${LD_EDITORFILE:-$LD_CONFIG_FOLDER/editor.src}"
|
||||
LD_ESOURCEFILE="${LD_ESOURCEFILE:-$LD_CONFIG_FOLDER/extra.src}"
|
||||
|
||||
if [[ -z "$LD_FOLDER" ]]; then
|
||||
LD_FOLDER=$(dirname "$(realpath "$0")")
|
||||
fi
|
||||
|
||||
ld_dbg()
|
||||
{
|
||||
if [[ $_LD_DEBUG == 1 ]]; then
|
||||
echo "DEBUG: $*" >&2
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_editor()
|
||||
{
|
||||
local editor=${LD_EDITOR:-$EDITOR}
|
||||
ld_dbg "Opening $editor to edit file: $1"
|
||||
$editor "$1"
|
||||
}
|
||||
|
||||
_daisy_enc()
|
||||
{
|
||||
local enc_is_folder="${ENC_IS_FOLDER:-0}"
|
||||
if [ -t 0 ] && [ -z "$1" ]; then
|
||||
echo "# $0: No arguments or stdin specified!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ ! -t 0 ] && [ -z "$1" ]; then
|
||||
echo "# $0: Please provide a filename as argument when using stdin"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ -n "$1" ] && [ -d "$1" ]; then
|
||||
echo -e "daisy_create_folder=$1"
|
||||
else
|
||||
local file_dir=""
|
||||
local file_name=""
|
||||
local perms=755
|
||||
local target=$1
|
||||
|
||||
if [[ ! -t 0 ]] && [[ $enc_is_folder == 0 ]]; then
|
||||
file_dir="."
|
||||
file_name="$1"
|
||||
elif [ -f "$1" ]; then
|
||||
file_dir=$(dirname "$1")
|
||||
file_name=$(basename "$1")
|
||||
perms=$(stat -c %a "$1")
|
||||
else
|
||||
echo "# $0: An error occured during encoding."
|
||||
return 1
|
||||
fi
|
||||
|
||||
local base64_inner
|
||||
base64_inner=$(cat "${1:-/dev/stdin}" | base64 | tr -d '\n')
|
||||
echo -e "daisy_folder_$file_name=$file_dir"
|
||||
echo -e "daisy_data_base64_$file_name=\"$base64_inner\""
|
||||
echo -e "daisy_perms_$file_name=$perms"
|
||||
fi
|
||||
}
|
||||
|
||||
_daisy_dec()
|
||||
{
|
||||
if [ -t 0 ] && [ -z "$1" ]; then
|
||||
echo "$0: No arguments or stdin specified!"
|
||||
return 1
|
||||
fi
|
||||
local data
|
||||
data=$(cat "${1:-/dev/stdin}" | grep -v "#")
|
||||
echo -e "$data" | cut -d "=" -f 2- | cut -b 2- | head -c -2 | base64 -d
|
||||
}
|
||||
|
||||
_daisy_unalias()
|
||||
{
|
||||
local unalias_param="$1"
|
||||
if [[ $unalias_param =~ ^[0-9]+$ ]]; then
|
||||
unalias_param=$(head -"$unalias_param" "$LD_ALIASFILE" 2>/dev/null | tail -1 | cut -d "=" -f 1 | awk '{print $2}')
|
||||
fi
|
||||
if [[ -z "$unalias_param" ]]; then
|
||||
return
|
||||
fi
|
||||
if [[ -f "$LD_ALIASFILE" ]]; then
|
||||
local newdata
|
||||
newdata=$(grep -v "alias $unalias_param" "$LD_ALIASFILE" 2>/dev/null)
|
||||
cp "$LD_ALIASFILE" "$LD_ALIASFILE.bak" 2>/dev/null
|
||||
echo -e "$newdata" > "$LD_ALIASFILE"
|
||||
fi
|
||||
|
||||
source "$LD_ALIASFILE"
|
||||
echo "Sourcing..."
|
||||
}
|
||||
|
||||
# --- Command Functions ---
|
||||
|
||||
cmd_help()
|
||||
{
|
||||
local target_tool="$1"
|
||||
local file="$LD_FOLDER/README.md"
|
||||
|
||||
# 1. Extract the block between the help markers
|
||||
sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
|
||||
if [ -z "$target_tool" ]; then
|
||||
# If no argument, print the whole help text
|
||||
cat
|
||||
else
|
||||
# 2. Parse specific tool
|
||||
awk -v query="$target_tool" '
|
||||
BEGIN { found=0; printing=0 }
|
||||
|
||||
# Match lines defining tools (e.g., "< cdz >" or "< daisy welcome >")
|
||||
$0 ~ /^[[:space:]]*< .* >/ {
|
||||
printing=0 # Stop printing previous tool
|
||||
|
||||
# Clean the line to get the "signature"
|
||||
# "< daisy welcome >" becomes "daisy welcome"
|
||||
sig = $0
|
||||
sub(/^[[:space:]]*< /, "", sig)
|
||||
sub(/ >[[:space:]]*$/, "", sig)
|
||||
|
||||
# Check for exact match OR match within a slash/space-separated list
|
||||
split(sig, names, "[ /]")
|
||||
|
||||
is_match = 0
|
||||
if (sig == query) is_match = 1
|
||||
else {
|
||||
for (i in names)
|
||||
{
|
||||
if (names[i] == query)
|
||||
{ is_match = 1; break }
|
||||
}
|
||||
}
|
||||
|
||||
if (is_match)
|
||||
{
|
||||
printing=1
|
||||
found=1
|
||||
print $0
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
# Print description lines if we are in a "found" block
|
||||
printing {
|
||||
# Stop if we hit the start of the NEXT tool
|
||||
if ($0 ~ /^[[:space:]]*< /)
|
||||
{ printing=0; next }
|
||||
print
|
||||
}
|
||||
|
||||
END {
|
||||
if (found == 0)
|
||||
{
|
||||
print "Tool '"'"'" query "'"'"' not found in README.md."
|
||||
}
|
||||
}
|
||||
'
|
||||
fi
|
||||
}
|
||||
|
||||
cmd_list()
|
||||
{
|
||||
local file="$LD_FOLDER/README.md"
|
||||
if [[ ! -f "$file" ]]; then
|
||||
echo "README.md not found at $file"
|
||||
exit 1
|
||||
fi
|
||||
echo "Available LACKADAISICAL commands:"
|
||||
sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
|
||||
awk '
|
||||
/^[[:space:]]*< / {
|
||||
sub(/^[[:space:]]*< /, "");
|
||||
sub(/ >[[:space:]]*$/, "");
|
||||
print " " $0
|
||||
}
|
||||
' | sort
|
||||
}
|
||||
|
||||
cmd_enc()
|
||||
{
|
||||
case "$1" in
|
||||
multi)
|
||||
shift
|
||||
for f in "$@"; do _daisy_enc "$f"; done
|
||||
;;
|
||||
folder)
|
||||
if ! command -v tree >/dev/null 2>&1; then
|
||||
echo "This function requires the utility 'tree'. Please install it."
|
||||
exit 1
|
||||
fi
|
||||
shift
|
||||
local dir="$1"
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
echo "Directory not found: $dir"
|
||||
exit 1
|
||||
fi
|
||||
cd "$dir" || exit 1
|
||||
tree -fia --noreport . | sed 1d | while read -r item; do
|
||||
ENC_IS_FOLDER=1 _daisy_enc "$item"
|
||||
done
|
||||
;;
|
||||
*)
|
||||
_daisy_enc "$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
cmd_dec()
|
||||
{
|
||||
case "$1" in
|
||||
multi)
|
||||
shift
|
||||
local arg1=$1
|
||||
local arg2=$2
|
||||
if [ ! -t 0 ]; then
|
||||
arg2=$1
|
||||
arg1=/dev/stdin
|
||||
fi
|
||||
[[ -t 0 ]] && [[ ! -f "$arg1" ]] && echo "daisy dec multi: No input file specified" && exit 1
|
||||
[[ ! -d "$arg2" ]] && echo "daisy dec multi: No output directory specified" && exit 1
|
||||
|
||||
local folder=""
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == "daisy_create_folder="* ]]; then
|
||||
folder=$(echo "$line" | cut -d "=" -f 2)
|
||||
mkdir -p "$arg2/$folder"
|
||||
elif [[ "$line" == "daisy_folder"* ]]; then
|
||||
folder=$(echo "$line" | cut -d "=" -f 2)
|
||||
elif [[ "$line" == "daisy_data_base64"* ]]; then
|
||||
local file=$(echo "$line" | cut -d "_" -f 4- | cut -d "=" -f 1)
|
||||
mkdir -p "$arg2/$folder"
|
||||
_daisy_dec <(echo "$line") > "$arg2/$folder/$file"
|
||||
elif [[ "$line" == "daisy_perms"* ]]; then
|
||||
local file=$(echo "$line" | cut -d "_" -f 3- | cut -d "=" -f 1)
|
||||
local perms=$(echo "$line" | cut -d "_" -f 3- | cut -d "=" -f 2)
|
||||
chmod "$perms" "$arg2/$folder/$file"
|
||||
fi
|
||||
done < "$arg1"
|
||||
;;
|
||||
*)
|
||||
_daisy_dec "$@"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
cmd_alias()
|
||||
{
|
||||
local alias_param="$*"
|
||||
if [[ -z "$alias_param" ]]; then
|
||||
echo "Active lackadaisical alias lines:"
|
||||
local linenum=1
|
||||
if [[ -f "$LD_ALIASFILE" ]]; then
|
||||
while IFS= read -r line; do
|
||||
line=$(echo "$line" | sed 's/alias //g')
|
||||
echo "$linenum: $line"
|
||||
((linenum++))
|
||||
done < "$LD_ALIASFILE"
|
||||
fi
|
||||
else
|
||||
local alias_name=$(echo "$alias_param" | grep -o ".*=" | tr -d =)
|
||||
if [[ $alias_name =~ ^[0-9]+$ ]]; then
|
||||
echo "An alias cannot start with a number! Exiting."
|
||||
exit 1
|
||||
fi
|
||||
_daisy_unalias "$alias_name"
|
||||
echo "alias ${alias_param%=*}=\"${alias_param#*=}\"" >> "$LD_ALIASFILE"
|
||||
fi
|
||||
source "$LD_ALIASFILE"
|
||||
echo "Sourcing..."
|
||||
}
|
||||
|
||||
cmd_clear()
|
||||
{
|
||||
find "$LD_CONFIG_FOLDER" -name "*.src" -type f | while read -r f; do
|
||||
cp -R "$f" "$f.bak"
|
||||
echo "Removing config file: $f"
|
||||
rm -rf "$f"
|
||||
done
|
||||
echo "Config cleared. Use 'daisy restore' if you would like to undo this."
|
||||
}
|
||||
|
||||
cmd_restore()
|
||||
{
|
||||
find "$LD_CONFIG_FOLDER" -name "*.src.bak" -type f | while read -r f; do
|
||||
local target="${f%.bak}"
|
||||
cp -R "$f" "$target"
|
||||
rm -rf "$f"
|
||||
echo "Restored backup: $target <-- $f"
|
||||
done
|
||||
echo "Config restored. Backups have been retained."
|
||||
}
|
||||
|
||||
cmd_check()
|
||||
{
|
||||
local failed=0
|
||||
local output=""
|
||||
|
||||
check_bin()
|
||||
{
|
||||
str=""
|
||||
if command -v "$1" >/dev/null 2>&1; then
|
||||
str="[ \e[32mOK\e[0m ] $1\n"
|
||||
else
|
||||
str="[ \e[31m--\e[0m ] $1 ($2)\n"
|
||||
failed=1
|
||||
fi
|
||||
output+=$str
|
||||
echo -e -n "$str"
|
||||
}
|
||||
|
||||
echo "--- Core (Essential) ---"
|
||||
check_bin bash "Shell environment"
|
||||
check_bin awk "Text processing"
|
||||
check_bin sed "Stream editing"
|
||||
check_bin grep "Pattern matching"
|
||||
check_bin base64 "Data encoding"
|
||||
check_bin realpath "Path resolution"
|
||||
|
||||
echo -e "\n--- Enhanced UI & Navigation ---"
|
||||
check_bin fzf "Used by cdf"
|
||||
check_bin peco "Used by cdp, editpeco"
|
||||
check_bin tree "Used by cdp, editpeco, daisy_enc_folder"
|
||||
check_bin dialog "Used by ched"
|
||||
|
||||
echo -e "\n--- Archives & Filesystems ---"
|
||||
check_bin archivemount "Used by cdz (mounting)"
|
||||
check_bin tar "Used by cdz (extraction)"
|
||||
check_bin unzip "Used by cdz (extraction)"
|
||||
check_bin unrar "Used by cdz (extraction)"
|
||||
check_bin mksquashfs "Used by squasher make"
|
||||
check_bin rsync "Used by squasher destroy"
|
||||
check_bin sshfs "Used by sshp"
|
||||
check_bin fusermount "Used by sshp, cdz"
|
||||
|
||||
echo -e "\n--- System ---"
|
||||
check_bin sudo "Privilege escalation"
|
||||
check_bin systemctl "Service management"
|
||||
check_bin perl "Advanced error reporting"
|
||||
|
||||
echo "=========================================="
|
||||
echo "Check complete."
|
||||
echo "=========================================="
|
||||
|
||||
[[ DAISY_IGNORE_DEPS -eq 1 ]] && return 0
|
||||
|
||||
[[ $failed -eq 1 ]] && ex_msg="Missing packages. DAISY_IGNORE_DEPS=1 to override"
|
||||
|
||||
if [ $failed -eq 1 ] ; then
|
||||
echo "Dependency report for LACKADAISICAL..."
|
||||
echo "=========================================="
|
||||
echo -e "$output"
|
||||
echo "=========================================="
|
||||
echo "Missing packages. DAISY_IGNORE_DEPS=1 to override"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
cmd_combine()
|
||||
{
|
||||
local cmds=()
|
||||
local args=()
|
||||
local separator_found=false
|
||||
|
||||
for item in "$@"; do
|
||||
if [[ "$item" == "--" ]]; then
|
||||
separator_found=true
|
||||
continue
|
||||
fi
|
||||
|
||||
if $separator_found; then
|
||||
args+=("$item")
|
||||
else
|
||||
cmds+=("$item")
|
||||
fi
|
||||
done
|
||||
|
||||
for cmd in "${cmds[@]}"; do
|
||||
set -- "${args[@]}"
|
||||
eval "$cmd"
|
||||
done
|
||||
}
|
||||
|
||||
# --- Dispatcher ---
|
||||
daisy ()
|
||||
{
|
||||
case "$1" in
|
||||
help) shift; cmd_help "$@" ;;
|
||||
list) shift; cmd_list "$@" ;;
|
||||
enc) shift; cmd_enc "$@" ;;
|
||||
dec) shift; cmd_dec "$@" ;;
|
||||
alias) shift; cmd_alias "$@" ;;
|
||||
unalias) shift; _daisy_unalias "$@" ;;
|
||||
backup) shift; find "$LD_CONFIG_FOLDER" -name "*.src" -type f | while read -r f; do cp -R "$f" "$f.bak"; echo "Backup made: $f --> $f.bak"; done ;;
|
||||
clear) shift; cmd_clear ;;
|
||||
check) shift; cmd_check ;;
|
||||
restore) shift; cmd_restore ;;
|
||||
combine) shift; cmd_combine ;;
|
||||
editor) shift; cmd_editor "$@" ;;
|
||||
wait)
|
||||
if [[ "$2" == "for" && "$3" == "editor" ]]; then
|
||||
shift 3
|
||||
_daisy_wait_for_editor "$@"
|
||||
else
|
||||
echo "Unknown daisy command: wait $*"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
reload)
|
||||
LD_INTERNAL=0 source "$LD_SOURCE_FILE"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown daisy command: $1"
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
379
daisy.source
379
daisy.source
|
|
@ -1,3 +1,4 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env -S echo "This file can only be sourced, not run stand-alone."
|
||||
# LACKADAISICAL SOURCE-ABLE FILE
|
||||
|
||||
|
|
@ -63,21 +64,20 @@ export LD_AVAILABLE=0
|
|||
|
||||
# Config folder setup
|
||||
export LD_CONFIG_FOLDER="$HOME/.config/lackadaisical"
|
||||
new_install=0
|
||||
export LD_NEW_INSTALL=
|
||||
|
||||
if [[ ! -d "$LD_CONFIG_FOLDER" ]];
|
||||
then
|
||||
# Create the folder with its basics
|
||||
mkdir -p "$LD_CONFIG_FOLDER"
|
||||
daisy_help
|
||||
new_install=1
|
||||
fi
|
||||
|
||||
# Multiple default source files
|
||||
# [LEA.TODO] Turn these into arrays
|
||||
LD_ALIASFILE="$LD_CONFIG_FOLDER/aliases.src"
|
||||
LD_EDITORFILE="$LD_CONFIG_FOLDER/editor.src"
|
||||
LD_ESOURCEFILE="$LD_CONFIG_FOLDER/extra.src"
|
||||
export LD_ALIASFILE="$LD_CONFIG_FOLDER/aliases.src"
|
||||
export LD_EDITORFILE="$LD_CONFIG_FOLDER/editor.src"
|
||||
export LD_ESOURCEFILE="$LD_CONFIG_FOLDER/extra.src"
|
||||
touch $LD_ALIASFILE
|
||||
touch $LD_EDITORFILE
|
||||
touch $LD_ESOURCEFILE
|
||||
|
|
@ -90,8 +90,8 @@ ld_dbg cat $LD_ESOURCEFILE
|
|||
# Source everything in the config folder
|
||||
function _daisy_source_configs
|
||||
{
|
||||
while IFS= read -r -d '' f; do
|
||||
source "$f"
|
||||
while IFS= read -r -d '' f; do
|
||||
source "$f"
|
||||
done < <(find "$LD_CONFIG_FOLDER" -name "*.src" -type f -print0)
|
||||
}
|
||||
|
||||
|
|
@ -101,7 +101,6 @@ then
|
|||
export PATH="$PATH:$LD_FOLDER"
|
||||
fi
|
||||
|
||||
|
||||
# Set up the basic alias for `shrc`
|
||||
# Do not set these up if LD_INTERNAL=1 is set, or infinite recursion could
|
||||
# occur!
|
||||
|
|
@ -114,26 +113,6 @@ fi
|
|||
# FUNCTIONS and ALIASES #######################################################
|
||||
###############################################################################
|
||||
|
||||
# Undocumented but internally used
|
||||
function daisy_wait_for_editor
|
||||
{
|
||||
pname="$1"
|
||||
fname="$2"
|
||||
|
||||
# Give some time for a process to launch
|
||||
sleep 1
|
||||
|
||||
while true;
|
||||
do
|
||||
alive=$(pgrep -f "$pname.*$fname")
|
||||
if [[ $alive == "" ]]
|
||||
then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
}
|
||||
|
||||
function multicd
|
||||
{
|
||||
cdpath="$@"
|
||||
|
|
@ -158,16 +137,6 @@ function multicd
|
|||
|
||||
alias cd=multicd
|
||||
|
||||
# Undocumented but internally used
|
||||
function daisy_editor
|
||||
{
|
||||
editor=${LD_EDITOR:-$EDITOR};
|
||||
ld_dbg echo Opening $editor to edit file: $1
|
||||
$editor "$1"
|
||||
sleep 1
|
||||
daisy_wait_for_editor $editor "$1"
|
||||
}
|
||||
|
||||
# bak and unbak
|
||||
function bak
|
||||
{
|
||||
|
|
@ -319,158 +288,16 @@ function ched
|
|||
source "$LD_EDITORFILE"
|
||||
}
|
||||
|
||||
function daisy_reload
|
||||
{
|
||||
LD_INTERNAL=0 source "$LD_SOURCE_FILE"
|
||||
}
|
||||
|
||||
function ldrc
|
||||
{
|
||||
ARG=$1
|
||||
SOURCE="$LD_SOURCE_FILE"
|
||||
[[ "$ARG" == "-e" ]] && SOURCE="$LD_ESOURCEFILE"
|
||||
|
||||
daisy_editor "$SOURCE"
|
||||
|
||||
daisy editor "$SOURCE"
|
||||
LD_INTERNAL=0 source "$SOURCE"
|
||||
}
|
||||
|
||||
enc_is_folder=0
|
||||
function daisy_enc
|
||||
{
|
||||
if [ -t 0 ] && [ -z "$1" ];
|
||||
then
|
||||
echo "# $0: No arguments or stdin specified!"
|
||||
return 1;
|
||||
fi
|
||||
|
||||
if [ ! -t 0 ] && [ -z "$1" ];
|
||||
then
|
||||
echo "# $0: Please provide a filename as argument when using stdin"
|
||||
return 1;
|
||||
fi
|
||||
|
||||
if [ -n "$1" ] && [ -d "$1" ];
|
||||
then
|
||||
echo -e "daisy_create_folder=$1"
|
||||
else
|
||||
file_dir=""
|
||||
file_name=""
|
||||
perms=755
|
||||
|
||||
target=$1
|
||||
|
||||
# [TODO, FIX: An unknown bug is causing daisy_enc_folder to misbehave if stdin is accessed, so we disable it here.]
|
||||
if [[ ! -t 0 ]] && [[ $enc_is_folder == 0 ]];
|
||||
then
|
||||
file_dir="."
|
||||
file_name="$1"
|
||||
shift
|
||||
elif [ -f "$1" ];
|
||||
then
|
||||
file_dir=$(dirname "$1")
|
||||
file_name=$(basename "$1")
|
||||
perms=$(stat -c %a "$1")
|
||||
else
|
||||
echo "# $0: An error occured during encoding."
|
||||
return 1
|
||||
fi
|
||||
|
||||
base64_inner=$(cat ${1:-/dev/stdin} | base64 | tr -d '\n')
|
||||
|
||||
# Print out our block
|
||||
echo -e "daisy_folder_$file_name=$file_dir"
|
||||
echo -e "daisy_data_base64_$file_name=\"$base64_inner\""
|
||||
echo -e "daisy_perms_$file_name=$perms"
|
||||
fi
|
||||
}
|
||||
|
||||
# Will only take input files, always outputs to stdout
|
||||
function daisy_enc_multi
|
||||
{
|
||||
for file in "$@"; do
|
||||
daisy_enc "$file"
|
||||
done
|
||||
}
|
||||
|
||||
function daisy_enc_folder
|
||||
{
|
||||
if [[ $LD_HAS_tree != 1 ]];
|
||||
then
|
||||
echo "This function requires the utiliy 'tree'. Please install it."
|
||||
return 1
|
||||
fi
|
||||
|
||||
dir="$1"
|
||||
cd "$dir"
|
||||
tree -fia --noreport . | sed 1d | while read -r item;
|
||||
do
|
||||
enc_is_folder=1
|
||||
daisy_enc "$item"
|
||||
enc_is_folder=0
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
function daisy_dec
|
||||
{
|
||||
if [ -t 0 ] && [ -z "$1" ];
|
||||
then
|
||||
echo "$0: No arguments or stdin specified!"
|
||||
return 1;
|
||||
fi
|
||||
|
||||
data=$(cat ${1:-/dev/stdin} | grep -v "#" )
|
||||
echo -e "$data" | cut -d "=" -f 2- | cut -b 2- | head -c -2 | base64 -d
|
||||
}
|
||||
|
||||
# Will only take a file and directory, sources it to find all encoded data
|
||||
# Extracts to the directory
|
||||
function daisy_dec_multi
|
||||
{
|
||||
arg1=$1
|
||||
arg2=$2
|
||||
|
||||
# Handle stdin support
|
||||
if [ ! -t 0 ];
|
||||
then
|
||||
arg2=$1
|
||||
arg1=/dev/stdin
|
||||
fi
|
||||
|
||||
[[ -t 0 ]] && [[ ! -f $arg1 ]] && echo "daisy_dec_multi: No input file specified" && return
|
||||
[[ ! -d $arg2 ]] && echo "daisy_dec_multi: No output directory specified" && return
|
||||
|
||||
folder=
|
||||
while IFS= read -r line; do
|
||||
if [[ "$line" == "daisy_create_folder="* ]];
|
||||
then
|
||||
folder=$(echo $line | cut -d "=" -f 2)
|
||||
echo $folder
|
||||
mkdir -p "$arg2/$folder"
|
||||
fi
|
||||
|
||||
if [[ "$line" == "daisy_folder"* ]];
|
||||
then
|
||||
folder=$(echo -e $line | cut -d "=" -f 2)
|
||||
continue
|
||||
fi
|
||||
|
||||
if [[ "$line" == "daisy_data_base64"* ]];
|
||||
then
|
||||
file=$(echo -e $line | cut -d "_" -f 4- | cut -d "=" -f 1)
|
||||
mkdir -p "$arg2/$folder"
|
||||
daisy_dec <(echo $line) > "$arg2/$folder/$file"
|
||||
fi
|
||||
|
||||
if [[ "$line" == "daisy_perms"* ]];
|
||||
then
|
||||
file=$(echo -e $line | cut -d "_" -f 3- | cut -d "=" -f 1)
|
||||
perms=$(echo -e $line | cut -d "_" -f 3- | cut -d "=" -f 2)
|
||||
chmod $perms "$arg2/$folder/$file"
|
||||
fi
|
||||
done <<< $(cat "$arg1")
|
||||
}
|
||||
|
||||
# Saves a bit on typing
|
||||
function grab
|
||||
{
|
||||
|
|
@ -496,95 +323,13 @@ function clip
|
|||
echo "Variable set to \"$LD_CLIP\"."
|
||||
}
|
||||
|
||||
function daisy_unalias
|
||||
{
|
||||
unalias_param=$@
|
||||
|
||||
if [[ $unalias_param =~ '^[0-9]+$' ]]; then
|
||||
selection=$(head -$unalias_param "$LD_ALIASFILE" | tail -1 | cut -d "=" -f 1 | grab 2)
|
||||
daisy_unalias $selection
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -z $unalias_param ]]; then
|
||||
return
|
||||
fi
|
||||
|
||||
unalias $@ 2>/dev/null
|
||||
|
||||
# Remove from aliases list
|
||||
newdata=$(cat "$LD_ALIASFILE" | grep -v "alias $unalias_param")
|
||||
[[ NO_BAK -lt 1 ]] && bak "$LD_ALIASFILE" 1>/dev/null
|
||||
echo -e $newdata > "$LD_ALIASFILE"
|
||||
}
|
||||
|
||||
function daisy_alias
|
||||
{
|
||||
alias_param="$@"
|
||||
|
||||
if [[ -z $alias_param ]]; then
|
||||
linenum=1
|
||||
echo "Active lackadaisical alias lines:"
|
||||
while IFS= read -r line; do
|
||||
line=$(echo "$line" | sed 's/alias / /g')
|
||||
echo "$linenum: $line"
|
||||
linenum=$(($linenum + 1))
|
||||
done < "$LD_ALIASFILE"
|
||||
return
|
||||
fi
|
||||
|
||||
# Plain name and contents
|
||||
alias_name=$(echo -e $alias_param | grep -o ".*=" | tr --delete =)
|
||||
|
||||
if [[ $alias_name =~ '^[0-9]+$' ]]; then
|
||||
echo "An alias cannot start with a number! Exiting."
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Make persistent
|
||||
daisy_unalias $alias_name
|
||||
echo alias ${alias_param%=*}"="\"${alias_param#*=}\" >> $LD_ALIASFILE
|
||||
source $LD_ALIASFILE
|
||||
}
|
||||
|
||||
function daisy_backup
|
||||
{
|
||||
for f in `find "$LD_CONFIG_FOLDER" -name "*.src" -type f`;
|
||||
do
|
||||
bak "$f"
|
||||
done
|
||||
}
|
||||
|
||||
function daisy_clear
|
||||
{
|
||||
daisy_backup
|
||||
|
||||
for f in `find "$LD_CONFIG_FOLDER" -name "*.src" -type f`;
|
||||
do
|
||||
echo "Removing config file: $f"
|
||||
rm -rf "$f"
|
||||
done
|
||||
|
||||
echo "Config cleared. Use 'daisy_restore' if you would like to undo this."
|
||||
daisy_reload
|
||||
}
|
||||
|
||||
function daisy_restore
|
||||
{
|
||||
for f in `find "$LD_CONFIG_FOLDER" -name "*.src" -type f`;
|
||||
do
|
||||
unbak "$f"
|
||||
bak "$f" 1>/dev/null
|
||||
done
|
||||
|
||||
echo "Config restored. Backups have been retained."
|
||||
daisy_reload
|
||||
}
|
||||
|
||||
# Aliases for front-facing daisy_ functions
|
||||
# Aliases for front-facing daisy commands
|
||||
function _daisy_def_alias
|
||||
{
|
||||
alias ld_$1=daisy_$1
|
||||
# Map underscores in name to spaces in command if needed
|
||||
local cmd=$(echo $1 | tr '_' ' ')
|
||||
alias ld_$1="daisy $cmd"
|
||||
alias daisy_$1="daisy $cmd"
|
||||
}
|
||||
|
||||
_daisy_def_alias reload
|
||||
|
|
@ -598,97 +343,31 @@ _daisy_def_alias unalias
|
|||
_daisy_def_alias backup
|
||||
_daisy_def_alias clear
|
||||
_daisy_def_alias restore
|
||||
_daisy_def_alias combine
|
||||
_daisy_def_alias help
|
||||
_daisy_def_alias list
|
||||
|
||||
_daisy_source_configs
|
||||
|
||||
###############################################################################
|
||||
# check for dependencies @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||
###############################################################################
|
||||
if [[ $new_install -eq 1 ]];
|
||||
then
|
||||
daisy check
|
||||
fi
|
||||
|
||||
###############################################################################
|
||||
# end of FUNCTIONS and ALIASES ################################################
|
||||
###############################################################################
|
||||
|
||||
source "/etc/lackadaisical/daisy.command.source"
|
||||
|
||||
###############################################################################
|
||||
# Autocomplete for `daisy` command ############################################
|
||||
###############################################################################
|
||||
|
||||
# End of user section!
|
||||
export LD_AVAILABLE=1
|
||||
|
||||
[ -d "$LD_FOLDER" ] && export LD_AVAILABLE=1
|
||||
|
||||
# Help function, courtesy of Google Gemini
|
||||
function daisy_help()
|
||||
{
|
||||
local target_tool="$1"
|
||||
local file="$LD_FOLDER/README.md"
|
||||
|
||||
# 1. Extract the block between the new headers
|
||||
sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
|
||||
if [ -z "$target_tool" ]; then
|
||||
# If no argument, print the whole help text
|
||||
cat
|
||||
else
|
||||
# 2. Parse specific tool
|
||||
awk -v query="$target_tool" '
|
||||
BEGIN { found=0; printing=0 }
|
||||
|
||||
# Match lines defining tools (e.g., " - calm:" or " - bak/unbak:")
|
||||
$0 ~ /^[[:space:]]*- / {
|
||||
printing=0 # Stop printing previous tool
|
||||
|
||||
# Clean the line to get the "signature"
|
||||
# " - bak/unbak:" becomes "bak/unbak"
|
||||
sig = $0
|
||||
sub(/^[[:space:]]*- /, "", sig)
|
||||
sub(/:[[:space:]]*$/, "", sig)
|
||||
|
||||
# Check for exact match OR match within a slash-separated list
|
||||
# This handles "bak", "unbak", and "daisy_alias"
|
||||
split(sig, names, "/")
|
||||
|
||||
is_match = 0
|
||||
if (sig == query) is_match = 1
|
||||
else {
|
||||
for (i in names) {
|
||||
if (names[i] == query) { is_match = 1; break }
|
||||
}
|
||||
}
|
||||
|
||||
if (is_match) {
|
||||
printing=1
|
||||
found=1
|
||||
print $0 # Print the header line (e.g., " - bak/unbak:")
|
||||
next
|
||||
}
|
||||
}
|
||||
|
||||
# Print description lines if we are in a "found" block
|
||||
printing {
|
||||
# Stop if we hit the start of the NEXT tool
|
||||
if ($0 ~ /^[[:space:]]*- /) { printing=0; next }
|
||||
print
|
||||
}
|
||||
|
||||
END {
|
||||
if (found == 0) {
|
||||
print "Tool '"'"'" query "'"'"' not found in README.md."
|
||||
}
|
||||
}
|
||||
'
|
||||
fi
|
||||
}
|
||||
|
||||
# Courtesy of Google Gemini
|
||||
daisy_list()
|
||||
{
|
||||
local file="$LD_FOLDER/README.md"
|
||||
echo "Available LACKADAISICAL commands:"
|
||||
|
||||
# Extract block -> Find tool lines -> Clean formatting -> Print
|
||||
sed -n '/--- BEGIN OF DAISY HELP ---/,/--- END OF DAISY HELP ---/{//!p;}' "$file" |
|
||||
awk '
|
||||
/^[[:space:]]*- / {
|
||||
# Remove indentation and "- "
|
||||
sub(/^[[:space:]]*- /, "");
|
||||
# Remove trailing ":"
|
||||
sub(/:[[:space:]]*$/, "");
|
||||
print " " $0
|
||||
}
|
||||
' | sort
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,8 @@ case_cm2=" exec help_fn"
|
|||
case_cm3=" ;;"
|
||||
case_p2="esac"
|
||||
|
||||
func_p1="function $OPTION_fn() {"
|
||||
func_p1="function $OPTION_fn()
|
||||
{"
|
||||
func_p2=" exit($?)"
|
||||
func_p3="}"
|
||||
|
||||
|
|
|
|||
2
shrc
2
shrc
|
|
@ -14,5 +14,5 @@ shellname=$(basename $SHELL)
|
|||
rc_name="."$shellname"rc"
|
||||
rc_path="$HOME/$rc_name"
|
||||
|
||||
daisy_editor "$rc_path"
|
||||
daisy editor "$rc_path"
|
||||
source "$rc_path"
|
||||
|
|
|
|||
249
squasher
249
squasher
|
|
@ -6,13 +6,14 @@ BIN_DIR=$(dirname "$(readlink -f "$0")")
|
|||
COMMAND="$1"
|
||||
DIR="$2"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 {make|mount|umount|destroy} <directory>"
|
||||
exit 1
|
||||
usage()
|
||||
{
|
||||
echo "Usage: $0 {make|mount|umount|destroy} <directory>"
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [[ -z "$COMMAND" || -z "$DIR" ]]; then
|
||||
usage
|
||||
usage
|
||||
fi
|
||||
|
||||
DIR=$(readlink -f "$DIR")
|
||||
|
|
@ -24,156 +25,156 @@ OVERLAY_WORK="$OVERLAY_ROOT/work"
|
|||
OVERLAY_TARG="$DIR"
|
||||
|
||||
case "$COMMAND" in
|
||||
make)
|
||||
if [[ ! -d "$DIR" ]]; then
|
||||
echo "Error: Directory \"$DIR\" does not exist!"
|
||||
exit 1
|
||||
fi
|
||||
make)
|
||||
if [[ ! -d "$DIR" ]]; then
|
||||
echo "Error: Directory \"$DIR\" does not exist!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking system requirements (FUSE, SquashFS, OverlayFS)..."
|
||||
for fs in fuse squashfs overlay; do
|
||||
if ! grep -q "$fs" /proc/filesystems; then
|
||||
echo "Attempting to load $fs module..."
|
||||
sudo modprobe "$fs" || { echo "Error: $fs is not supported."; exit 1; }
|
||||
fi
|
||||
done
|
||||
echo "Checking system requirements (FUSE, SquashFS, OverlayFS)..."
|
||||
for fs in fuse squashfs overlay; do
|
||||
if ! grep -q "$fs" /proc/filesystems; then
|
||||
echo "Attempting to load $fs module..."
|
||||
sudo modprobe "$fs" || { echo "Error: $fs is not supported."; exit 1; }
|
||||
fi
|
||||
done
|
||||
|
||||
DIRSIZE=$(du -sh "$DIR" | cut -f1)
|
||||
RECREATE=false
|
||||
mkdir -p "$OVERLAY_ROOT"
|
||||
DIRSIZE=$(du -sh "$DIR" | cut -f1)
|
||||
RECREATE=false
|
||||
mkdir -p "$OVERLAY_ROOT"
|
||||
|
||||
if [[ -f "${OVERLAY_ROOT}.img" ]]; then
|
||||
echo "Existing image found, updating..."
|
||||
"$0" mount "$DIR"
|
||||
DIRSIZE=$(du -sh "$DIR" | cut -f1)
|
||||
RECREATE=true
|
||||
fi
|
||||
if [[ -f "${OVERLAY_ROOT}.img" ]]; then
|
||||
echo "Existing image found, updating..."
|
||||
"$0" mount "$DIR"
|
||||
DIRSIZE=$(du -sh "$DIR" | cut -f1)
|
||||
RECREATE=true
|
||||
fi
|
||||
|
||||
echo "Compressing \"$DIR\"..."
|
||||
sudo mksquashfs "$DIR" "${OVERLAY_ROOT}.img.1" -noappend -comp xz || exit 1
|
||||
echo "Compressing \"$DIR\"..."
|
||||
sudo mksquashfs "$DIR" "${OVERLAY_ROOT}.img.1" -noappend -comp xz || exit 1
|
||||
|
||||
if [[ "$RECREATE" == "true" ]]; then
|
||||
echo "Cleaning up old layers..."
|
||||
"$0" umount "$DIR"
|
||||
if [[ -n "$OVERLAY_ROOT" && "$OVERLAY_ROOT" != "/" ]]; then
|
||||
sudo rm -rf "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK"
|
||||
rm -f "${OVERLAY_ROOT}.img"
|
||||
fi
|
||||
fi
|
||||
if [[ "$RECREATE" == "true" ]]; then
|
||||
echo "Cleaning up old layers..."
|
||||
"$0" umount "$DIR"
|
||||
if [[ -n "$OVERLAY_ROOT" && "$OVERLAY_ROOT" != "/" ]]; then
|
||||
sudo rm -rf "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK"
|
||||
rm -f "${OVERLAY_ROOT}.img"
|
||||
fi
|
||||
fi
|
||||
|
||||
mv "${OVERLAY_ROOT}.img.1" "${OVERLAY_ROOT}.img"
|
||||
mkdir -p "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK" "$OVERLAY_TARG"
|
||||
mv "${OVERLAY_ROOT}.img.1" "${OVERLAY_ROOT}.img"
|
||||
mkdir -p "$OVERLAY_UPPER" "$OVERLAY_LOWER" "$OVERLAY_WORK" "$OVERLAY_TARG"
|
||||
|
||||
sudo rm -rf "$DIR"
|
||||
mkdir -p "$DIR"
|
||||
touch "$DIR/.needs_mount"
|
||||
sudo rm -rf "$DIR"
|
||||
mkdir -p "$DIR"
|
||||
touch "$DIR/.needs_mount"
|
||||
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "Storage Stats:"
|
||||
echo " Original size: $DIRSIZE"
|
||||
echo " Compressed: $(du -sh "${OVERLAY_ROOT}.img" | cut -f1)"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
echo "Storage Stats:"
|
||||
echo " Original size: $DIRSIZE"
|
||||
echo " Compressed: $(du -sh "${OVERLAY_ROOT}.img" | cut -f1)"
|
||||
echo "-------------------------------------------------------------------------"
|
||||
|
||||
SERVICE_CONTENT="[Unit]
|
||||
Description=SquashFS Mount for %I
|
||||
After=local-fs.target
|
||||
SERVICE_CONTENT="[Unit]
|
||||
Description=SquashFS Mount for %I
|
||||
After=local-fs.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=${BIN_DIR}/squasher mount %I
|
||||
ExecStop=${BIN_DIR}/squasher umount %I
|
||||
[Service]
|
||||
Type=oneshot
|
||||
RemainAfterExit=yes
|
||||
ExecStart=${BIN_DIR}/squasher mount %I
|
||||
ExecStop=${BIN_DIR}/squasher umount %I
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target"
|
||||
[Install]
|
||||
WantedBy=multi-user.target"
|
||||
|
||||
echo "$SERVICE_CONTENT" | sudo tee /etc/systemd/system/squash-mount@.service > /dev/null
|
||||
sudo systemctl daemon-reload
|
||||
echo "$SERVICE_CONTENT" | sudo tee /etc/systemd/system/squash-mount@.service > /dev/null
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
ESC_PATH=$(systemd-escape -p "$DIR")
|
||||
SERVICE_NAME="squash-mount@$ESC_PATH.service"
|
||||
ESC_PATH=$(systemd-escape -p "$DIR")
|
||||
SERVICE_NAME="squash-mount@$ESC_PATH.service"
|
||||
|
||||
read -p "Enable auto-mount service ($SERVICE_NAME)? [y/N] " yn
|
||||
read -p "Enable auto-mount service ($SERVICE_NAME)? [y/N] " yn
|
||||
|
||||
if [[ "$yn" =~ ^[Yy]$ ]]; then
|
||||
sudo systemctl enable --now "$SERVICE_NAME"
|
||||
sudo systemctl stop "$SERVICE_NAME"
|
||||
sudo systemctl start "$SERVICE_NAME"
|
||||
else
|
||||
echo "Manual mount command: sudo systemctl start $SERVICE_NAME"
|
||||
fi
|
||||
;;
|
||||
if [[ "$yn" =~ ^[Yy]$ ]]; then
|
||||
sudo systemctl enable --now "$SERVICE_NAME"
|
||||
sudo systemctl stop "$SERVICE_NAME"
|
||||
sudo systemctl start "$SERVICE_NAME"
|
||||
else
|
||||
echo "Manual mount command: sudo systemctl start $SERVICE_NAME"
|
||||
fi
|
||||
;;
|
||||
|
||||
mount)
|
||||
if [[ ! -f "${OVERLAY_ROOT}.img" ]]; then
|
||||
echo "Error: SquashFS image \"${OVERLAY_ROOT}.img\" not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
mount)
|
||||
if [[ ! -f "${OVERLAY_ROOT}.img" ]]; then
|
||||
echo "Error: SquashFS image \"${OVERLAY_ROOT}.img\" not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
"$0" umount "$DIR" 2>/dev/null
|
||||
mkdir -p "$OVERLAY_LOWER"
|
||||
sudo mount "${OVERLAY_ROOT}.img" "$OVERLAY_LOWER" -t squashfs -o loop
|
||||
"$0" umount "$DIR" 2>/dev/null
|
||||
mkdir -p "$OVERLAY_LOWER"
|
||||
sudo mount "${OVERLAY_ROOT}.img" "$OVERLAY_LOWER" -t squashfs -o loop
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Error: Failed to mount squashfs image." >&2
|
||||
exit 1
|
||||
fi
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Error: Failed to mount squashfs image." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo mount -t overlay none "$OVERLAY_TARG" \
|
||||
-o lowerdir="$OVERLAY_LOWER",upperdir="$OVERLAY_UPPER",workdir="$OVERLAY_WORK"
|
||||
sudo mount -t overlay none "$OVERLAY_TARG" \
|
||||
-o lowerdir="$OVERLAY_LOWER",upperdir="$OVERLAY_UPPER",workdir="$OVERLAY_WORK"
|
||||
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Error: Failed to mount overlay." >&2
|
||||
sudo umount "$OVERLAY_LOWER" 2>/dev/null
|
||||
exit 1
|
||||
fi
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Error: Failed to mount overlay." >&2
|
||||
sudo umount "$OVERLAY_LOWER" 2>/dev/null
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "SquashFS filesystem is mounted and ready."
|
||||
;;
|
||||
echo "SquashFS filesystem is mounted and ready."
|
||||
;;
|
||||
|
||||
umount)
|
||||
sudo umount -l -R "$OVERLAY_TARG" 2>/dev/null
|
||||
sudo umount -l -R "$OVERLAY_LOWER" 2>/dev/null
|
||||
umount)
|
||||
sudo umount -l -R "$OVERLAY_TARG" 2>/dev/null
|
||||
sudo umount -l -R "$OVERLAY_LOWER" 2>/dev/null
|
||||
|
||||
if mountpoint -q "$OVERLAY_TARG" || mountpoint -q "$OVERLAY_LOWER"; then
|
||||
echo "Warning: Filesystem is still mounted. Check for open processes."
|
||||
exit 1
|
||||
fi
|
||||
if mountpoint -q "$OVERLAY_TARG" || mountpoint -q "$OVERLAY_LOWER"; then
|
||||
echo "Warning: Filesystem is still mounted. Check for open processes."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "SquashFS filesystem has been unmounted."
|
||||
;;
|
||||
echo "SquashFS filesystem has been unmounted."
|
||||
;;
|
||||
|
||||
destroy)
|
||||
if [[ ! -f "$DIR/.needs_mount" ]]; then
|
||||
if ! mountpoint -q "$DIR"; then
|
||||
echo "Error: $DIR is not a SquashFS directory."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
destroy)
|
||||
if [[ ! -f "$DIR/.needs_mount" ]]; then
|
||||
if ! mountpoint -q "$DIR"; then
|
||||
echo "Error: $DIR is not a SquashFS directory."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
ESC_PATH=$(systemd-escape -p "$DIR")
|
||||
SERVICE_NAME="squash-mount@$ESC_PATH.service"
|
||||
ESC_PATH=$(systemd-escape -p "$DIR")
|
||||
SERVICE_NAME="squash-mount@$ESC_PATH.service"
|
||||
|
||||
echo "Disabling service ($SERVICE_NAME)..."
|
||||
sudo systemctl stop "$SERVICE_NAME" 2>/dev/null
|
||||
sudo systemctl disable "$SERVICE_NAME" 2>/dev/null
|
||||
echo "Disabling service ($SERVICE_NAME)..."
|
||||
sudo systemctl stop "$SERVICE_NAME" 2>/dev/null
|
||||
sudo systemctl disable "$SERVICE_NAME" 2>/dev/null
|
||||
|
||||
echo "Ensuring image is mounted to preserve data..."
|
||||
"$0" mount "$DIR" 1>/dev/null 2>/dev/null
|
||||
echo "Ensuring image is mounted to preserve data..."
|
||||
"$0" mount "$DIR" 1>/dev/null 2>/dev/null
|
||||
|
||||
echo "Destroying image and restoring data..."
|
||||
TEMP_DIR=$(mktemp -d /tmp/squash-dest.XXXXXXXX)
|
||||
sudo rsync -aX "$DIR/" "$TEMP_DIR/" || { echo "Error: Failed to copy data."; exit 1; }
|
||||
echo "Destroying image and restoring data..."
|
||||
TEMP_DIR=$(mktemp -d /tmp/squash-dest.XXXXXXXX)
|
||||
sudo rsync -aX "$DIR/" "$TEMP_DIR/" || { echo "Error: Failed to copy data."; exit 1; }
|
||||
|
||||
"$0" umount "$DIR"
|
||||
sudo rm -rf "$DIR"
|
||||
sudo mv "$TEMP_DIR" "$DIR"
|
||||
sudo rm -rf "$OVERLAY_ROOT" "${OVERLAY_ROOT}.img"
|
||||
"$0" umount "$DIR"
|
||||
sudo rm -rf "$DIR"
|
||||
sudo mv "$TEMP_DIR" "$DIR"
|
||||
sudo rm -rf "$OVERLAY_ROOT" "${OVERLAY_ROOT}.img"
|
||||
|
||||
echo "Success: SquashFS image destroyed and data restored to \"$DIR\"."
|
||||
;;
|
||||
echo "Success: SquashFS image destroyed and data restored to \"$DIR\"."
|
||||
;;
|
||||
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
*)
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
|
|
|||
3
sshp
3
sshp
|
|
@ -6,7 +6,8 @@ ssh_args=()
|
|||
remote_port=$((10000 + RANDOM % 10000))
|
||||
local_user=$(whoami)
|
||||
|
||||
usage() {
|
||||
usage()
|
||||
{
|
||||
echo "Usage: sshp -m <local>:<remote> [user@]host [ssh_options]"
|
||||
exit 1
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue