diff --git a/bin/mark b/bin/mark index a8ffa1e..7551dd5 100755 --- a/bin/mark +++ b/bin/mark @@ -2,10 +2,118 @@ nux.use nux/fs @prefix fs nux.fs. +@prefix check nux.check. -MARK_DIR_NAME=.by +MARK_DIR_NAME="${MARK_DIR_NAME:-.by}" MARK_PREFIX="" + +## Manages symlinks in closest mark (**.by**) directory, provides functionality to batch create +## them with relative paths. +## +## #Available tasks: +## tag:: +## Performs specified task in tag namespace (marks prefixed with **tag/**) +@command tag task { + MARK_PREFIX="tag/" + nuxr.run "$task" "$@" +} + +## this:: [marks...] +## Marks **current folder** with specific markers. +## This creates symlinks in **mark** folder pointing to **current folder**. +@command this mark { + nux.log debug "Args $#" + item=$(pwd) + mark_root=$(mark.dir "$item") + mark.mark "$mark_root" "$item" "$MARK_PREFIX$mark" + while [ "$#" -gt 0 ]; do + mark="$1"; shift; + mark.mark "$mark_root" "$item" "$MARK_PREFIX$mark" + done +} + +## multiple:: +## Marks **files** with specific **mark**. +## This creates symlinks for files in **mark** folder. +@command multiple mark { + pwd=$(pwd) + mark_root=$(mark.dir "$pwd") + while [ "$#" -gt 0 ]; do + item="$1"; shift; + mark.mark "$mark_root" "$pwd/$item" "$MARK_PREFIX$mark" + done +} + +## display:: [mark] +## Displays path to current mark folder and displays available marks. +## If **mark** is provided list nested marks. +@command display mark { + mark_root=$(mark.dir $pwd) + prefix="$MARK_PREFIX" + if [ -n "$mark" ]; then + prefix="$MARK_PREFIX$mark/"; + fi + echo $mark_root: + ( + cd "$mark_root"; + for mark in "$prefix"* ; do + echo ${mark#$MARK_PREFIX}; + done; + ) +} +## mark-to-target:: mark target [suffix] +## Moves non-symlinks to *target* and creates symlinks in mark folder +## This also applies to submarks +@command mark-to-target mark target { + suffix="$1"; + nux.log info "Suffix is $suffix" + mark=$(mark.dir $pwd)/$mark + nux.log debug $(mark.dir $pwd) $mark; + find "$mark" -type f | while read file; do + if ! nux.check.file.symlink "$file"; then + name=$(nux.fs.name "$file") + file_mark=$(nux.fs.dirname "$file") + fs:info "$file" Moving to $target/$name + fs:move "$target" "$file" + fs:info "$target/$name" Creating symlink in $file_mark + fs:symlink "$target/$name" "$file_mark" "$name" + fi + done +} + +## visual:: [image+] +## Display images using feh and allows adding marks using 1-9 key. +## The list of marks is speficied by environment variable *MARK_TAGS* +## +@command visual { + nux.require feh + marks=${MARK_TAGS:-person woman man selfie} + mark_root=$(nux.fs.path.relative.pwd $(mark.dir $pwd/)) + actions=""; + for mark in $marks; do + ((i++)) + mark=$MARK_PREFIX$mark + if [ $i -gt 9 ]; then + break; + fi + action="--action$i '[$mark] mkdir -p $mark_root/$mark; ln -svft $mark_root/$mark \$(realpath -Lms --relative-to=$mark_root/$mark %F)'"; + actions="$actions $action"; + + done; + nux.log debug Feh actions "$actions" + nux.eval feh \ + --zoom max \ + --scale-down \ + -g 900x1000 \ + -G \ + "--action '[keep]echo %F: Next file.'" \ + "$actions" \ + "--info 'echo %n: %wx%h'" \ + --draw-tinted "$@" +} + + @namespace mark. { function :dir item { if [ -n "$MARK_DIR" ]; then @@ -28,59 +136,3 @@ MARK_PREFIX="" } } - -## Manages symlinks in closest mark (**.by**) directory, provides functionality to batch create -## them with relative paths. -## -## #Available tasks: -@namespace task. { -## tag:: -## Performs specified task in tag namespace (marks prefixed with **tag/**) -@command tag task { - MARK_PREFIX="tag/" - nuxr.run "$task" "$@" - } - -## this:: [marks...] -## Marks **current folder** with specific markers. -## This creates symlinks in **mark** folder pointing to **current folder**. -@command this mark { - nux.log debug "Args $#" - item=$(pwd) - mark_root=$(mark.dir "$item") - mark.mark "$mark_root" "$item" "$MARK_PREFIX$mark" - while [ "$#" -gt 0 ]; do - mark="$1"; shift; - mark.mark "$mark_root" "$item" "$MARK_PREFIX$mark" - done - } - -## multiple:: -## Marks **files** with specific **mark**. -## This creates symlinks for files in **mark** folder. -@command multiple mark { - pwd=$(pwd) - mark_root=$(mark.dir "$pwd") - while [ "$#" -gt 0 ]; do - item="$1"; shift; - mark.mark "$mark_root" "$pwd/$item" "$MARK_PREFIX$mark" - done - } - -## display:: [mark] -## Displays path to current mark folder and displays available marks. -## If **mark** is provided list nested marks. -@command display mark { - mark_root=$(mark.dir $pwd) - prefix="$MARK_PREFIX" - if [ -n "$mark" ]; then - prefix="$MARK_PREFIX$mark/"; - fi - echo $mark_root: - ( - cd $(mark_root); - for mark in "$prefix"* ; do - echo ${mark#$MARK_PREFIX}; - done; - ) - } diff --git a/bin/vfs b/bin/vfs index 4bc5ce1..098cda1 100755 --- a/bin/vfs +++ b/bin/vfs @@ -4,17 +4,25 @@ nux.use nux/fs @prefix fs nux.fs. VFS_SOURCES_FILE=".vfs.sources" +declare -gA CURRENT_SOURCES +CURRENT_SOURCES_FILE="" +CURRENT_MOUNT="" -CURRENT_SOURCES_FILE=$(nux.fs.closest "$VFS_SOURCES_FILE"); +function vfs.init path { + CURRENT_SOURCES_FILE=$(nux.fs.closest "$VFS_SOURCES_FILE" "$path"); + vfs.merger.load $CURRENT_SOURCES_FILE; +} -if fs:exists "$CURRENT_SOURCES_FILE" { - CURRENT_MOUNT="${CURRENT_SOURCES_FILE%/*}"; - declare -gA CURRENT_SOURCES - nux.log debug "Current VFS mount: ${CURRENT_MOUNT%/*}"; +function vfs.merger.load path { + if fs:exists "$path" { + CURRENT_MOUNT="${path%/*}"; - while read name path; do - CURRENT_SOURCES[${name}]="$path" - done < "$CURRENT_SOURCES_FILE" + nux.log debug "Current VFS mount: ${CURRENT_MOUNT%/*}"; + + while read name path; do + CURRENT_SOURCES[${name}]="$path" + done < "$CURRENT_SOURCES_FILE" + } } function vfs.path name { @@ -31,6 +39,15 @@ function vfs.path.real file { done } +function vfs.path.real.all file { + for root in "${CURRENT_SOURCES[@]}" ; do + nux.log trace "Testing $root$file" + if fs:exists "${root}${file}" { + echo ${root}${file}; + } + done +} + ## list:: ## Lists all **mergerfs** based virtual filesystems managed by **vfs** tool @@ -40,7 +57,10 @@ function vfs.path.real file { ## info:: ## Displays info about current path -@command info { +@command info path { + : ${path:=.} + nux.log debug "path" $path + vfs.init "$path" nux.log debug "VFS mount: ${CURRENT_MOUNT}"; echo "path:" $CURRENT_MOUNT; echo "sources:" @@ -62,7 +82,8 @@ function vfs.path.real file { ### FIXME: Switch does not support merging of directories - @command switch storage { +@command switch storage { + vfs.init . target="$(vfs.path "$storage")" if [ -z "$target" ] { nux.fatal "$storage does not exists." @@ -101,20 +122,29 @@ function vfs.path.real file { source_path="${source_path%/}" nux.log debug " Source: $source_name Path: $source_path"; mount_paths="$mount_paths:${source_path}" - echo "$source_name $source_path" >> "$source_tempfs/.vfs.sources" + echo "$source_name $source_path" >> "$source_tempfs/$VFS_SOURCES_FILE" done - echo "temp $source_tempfs" >> "$source_tempfs/$VFS_SOURCES_FILE=" + echo "temp $source_tempfs" >> "$source_tempfs/$VFS_SOURCES_FILE" - mergerfs_mounts="$source_tempfs:${mount_paths}" + mergerfs_mounts="${source_tempfs}=RO${mount_paths}" nux.log debug "MergerFS command:" $mergerfs_mounts; mergerfs "$mergerfs_mounts" "$target" (cd $target; vfs info ) - } +} ## unmount:: ## Unmounts target VFS filesystem. @command :unmount target { + vfs.init "$target" + task.info "$target" fusermount -u "$target" fs:info "${CURRENT_SOURCES[temp]}" removing temporary metadata. fs:stage rm -rf "${CURRENT_SOURCES[temp]}" } + +@command path file { + : ${file:=.} + vfs.init "$file" + rooted_path="/$(realpath -m --relative-to="$CURRENT_MOUNT" ${file%/})"; + vfs.path.real.all "$rooted_path"; +}