From c90e3bf08b1c6f4426d0f72c76b1ac9a0a346efb Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sat, 10 Feb 2024 07:05:52 +0100 Subject: Add tools MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- tools/addlink | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tools/getlinks | 19 ++++++++++ tools/linkblink | 14 ++++++++ tools/queryforest | 80 +++++++++++++++++++++++++++++++++++++++++ tools/sortforest | 85 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 302 insertions(+) create mode 100755 tools/addlink create mode 100755 tools/getlinks create mode 100755 tools/linkblink create mode 100755 tools/queryforest create mode 100755 tools/sortforest diff --git a/tools/addlink b/tools/addlink new file mode 100755 index 0000000..66e93da --- /dev/null +++ b/tools/addlink @@ -0,0 +1,104 @@ +#!/bin/sh +set -e + +target="$1" +link="$2" + +if ! test $# = 2; then + printf 'usage: %s target link\n' "$0" >&2 + exit 1 +fi + +if ! test -d scalable || ! test -r icons.mk; then + printf 'could not find both scalable/ and icons.mk the current working directory\n' >&2 + exit 1 +fi + +T="$target" +L="$link" +while test $(printf '%s\n' "$T" "$L" | grep / | wc -l) = 2; do + Td="$(printf '%s\n' "$T" | cut -d / -f 1)" + Ld="$(printf '%s\n' "$L" | cut -d / -f 1)" + if test ! "$Td" = "$Ld"; then + break + fi + T="$(printf '%s\n' "$T" | cut -d / -f 2-)" + L="$(printf '%s\n' "$L" | cut -d / -f 2-)" +done +while printf '%s\n' "$L" | grep / > /dev/null; do + T="$(printf '../%s\n' "$T")" + L="$(printf '%s\n' "$L" | cut -d / -f 2-)" +done +expectedtarget="${T}.svg" + +if test -f "scalable/${link}.svg"; then + if test ! -L "scalable/${link}.svg"; then + currenttarget="not a symbolic link" + elif test "$(readlink "scalable/${link}.svg")" = "$expectedtarget"; then + currenttarget="links to $target" + else + currenttarget="symbolic link -> $target" + fi + printf '%s already exists (%s)\n' "scalable/${link}.svg" "$currenttarget" >&2 + exit 1 +fi + +targetentry="$(grep '^[[:space:]]*'"$target"'\\$' < icons.mk)" +test -n "$targetentry" +test $(printf '%s\n' "$targetentry" | wc -l) = 1 + +if grep '^[[:space:]]*'"$link"'\\$' < icons.mk > /dev/null; then + printf '%s is already listed in icons.mk, however its file does not exist\n' "$link" >&2 + exit 1 +fi + +indent="$(sed -n 's:^\([[:space:]]*\)'"$target"'\\$:\1:p' < icons.mk)" +targetentrysed="$(printf '^%s$\n' "$targetentry" | sed 's:[/\\]:\\&:g')" + +newiconsfile="$(sed /"$targetentrysed"/q < icons.mk && \ + printf '%s\t%s\\\n' "$indent" "$link" && \ + sed 1,/"$targetentrysed"/d < icons.mk)" + +test $(printf '%s\n' "$newiconsfile" | diff icons.mk - | wc -l) = 2 + +( ! printf '%s\n' "$newiconsfile" | diff -U1 icons.mk - >&2 ) + +T="$target" +L="$link" +while test $(printf '%s\n' "$T" "$L" | grep / | wc -l) = 2; do + Td="$(printf '%s\n' "$T" | cut -d / -f 1)" + Ld="$(printf '%s\n' "$L" | cut -d / -f 1)" + if test ! "$Td" = "$Ld"; then + break + fi + T="$(printf '%s\n' "$T" | cut -d / -f 2-)" + L="$(printf '%s\n' "$L" | cut -d / -f 2-)" +done +while printf '%s\n' "$L" | grep / > /dev/null; do + T="$(printf '../%s\n' "$T")" + L="$(printf '%s\n' "$L" | cut -d / -f 2-)" +done + +target="$expectedtarget" +link="scalable/${link}.svg" +printf 'ln -s %s %s\n' "$target" "$link" >&2 + +if ! cp icons.mk icons.mk~; then + printf 'failed to create backup of icons.mk\n' >&2 + exit 1 +fi +if ! ln -s "$target" "$link"; then + printf 'failed to create symbolic link %s -> %s\n' "$link" "$target" >&2 + rm -f icons.mk~ >&2 + exit 1 +fi +if ! printf '%s\n' "$newiconsfile" > icons.mk; then + printf 'failed to insert entry into icons.mk\n' >&2 + if ! unlink "$link" >&2; then + printf '\x1b[31mfailed to remove created symbolic link (%s)\x1b[m\n' "$link" >&2 + fi + if ! mv icons.mk~ icons.mk >&2; then + printf '\x1b[1;31mfailed to restore icons.mk using icons.mk~\x1b[m\n' >&2 + fi + exit 1 +fi diff --git a/tools/getlinks b/tools/getlinks new file mode 100755 index 0000000..b1a376a --- /dev/null +++ b/tools/getlinks @@ -0,0 +1,19 @@ +#!/bin/sh + +if test $# = 0; then + dir=. +else + dir="$1" + shift 1 +fi + +dirlen="${#dir}" +find "$dir" | xtest -L "$@" | colrm 1 $dirlen | sed 's/^\/*//' | while read f; do + L="$(printf '%s\n' "$f" | rev | cut -d . -f 2- | rev)" + T="$(dirname -- "$L")/$(readlink -- "$dir/$f" | rev | cut -d . -f 2- | rev)" + T="$(printf '%s\n' "$T" | sed 's:/\(./\)*:/:g')" + while printf '%s\n' "$T" | grep '/../' > /dev/null; do + T="$(printf '%s\n' "$T" | sed 's:[^/]*/\.\./::')" + done + printf '%s\n\t%s\n' "$T" "$L" +done diff --git a/tools/linkblink b/tools/linkblink new file mode 100755 index 0000000..fe0d842 --- /dev/null +++ b/tools/linkblink @@ -0,0 +1,14 @@ +#!/bin/sh + +if test $# = 0; then + printf 'usage: blink-on-icon ...' >&2 + exit 1 +fi + +for n; do + of="${n}.svg" + nf="${n}-blink_off.svg" + ot="$(readlink -- "${of}")" + nt="$(printf '%s\n' "$ot" | sed 's/\.svg$/-blink_off&/')" + ln -s "$nt" "$nf" +done diff --git a/tools/queryforest b/tools/queryforest new file mode 100755 index 0000000..8dc979c --- /dev/null +++ b/tools/queryforest @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +import sys, os + +args = sys.argv[1:] + +if len(args) == 0: + print('usage: %s (icon | file | directory) ... < icon-forest' % sys.argv[0], file = sys.stderr) + exit(1) + +forest = {} +selected = {} + +try: + while True: + line = input() + if not line.strip(): + continue + if not line.startswith('\t'): + tree = [] + icon = line.strip() + tree.append(line) + if icon in forest: + print('duplicate entry of %s found' % icon, file = sys.stderr) + forest[icon] = (tree, len(tree) - 1) +except EOFError: + pass + +basenames = {} +for icon in forest: + iconbasename = icon.split('/')[-1] + icons = basenames.get(iconbasename, []) + icons.append(icon) + basenames[iconbasename] = icons + +def select(icon): + if icon in forest: + (tree, line) = forest[icon] + lines = selected.get(tree[0], {}) + lines[line] = None + selected[tree[0]] = lines + elif icon.split('/')[-1] in basenames: + icondir = '/'.join(icon.split('/')[:-1]) + for alticon in basenames[icon.split('/')[-1]]: + (tree, line) = forest[alticon] + lines = selected.get(tree[0], {}) + if line not in lines: + lines[line] = [icondir] + elif lines[line] is None: + continue + else: + lines[line].append(icondir) + selected[tree[0]] = lines + +def visit(d): + for f in os.listdir(d): + f = d + '/' + f + if os.path.isfile(f): + icon = '/'.join('.'.join(f.split('.')[:-1]).split('/')[-2:]) + select(icon) + elif os.path.isdir(f): + visit(f) + +for icon in args: + if os.path.isfile(icon) and '/' in icon and icon.endswith('.svg'): + icon = '/'.join(icon[:-4].split('/')[-2:]) + elif os.path.isdir(icon): + visit(icon) + continue + select(icon) + +for tree in sorted(selected): + lines = selected[tree] + (tree, _) = forest[tree] + for i, line in enumerate(tree): + if i not in lines: + print(line) + elif lines[i] is None: + print('\033[1;31m%s\033[m' % line) + else: + print('\033[1;33m%s\033[;33m (%s)\033[m' % (line, ', '.join(sorted(lines[i])))) diff --git a/tools/sortforest b/tools/sortforest new file mode 100755 index 0000000..bbb2faa --- /dev/null +++ b/tools/sortforest @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +import sys + +if len(sys.argv) > 1: + print('usage: %s < icon-forest' % sys.argv[0], file = sys.stderr) + exit(1) + +standalone = set() +pairs = [] +stack = [] +try: + while True: + line = input() + if not line.strip(): + continue + indent = 0 + while line.startswith('\t'): + indent += 1 + line = line[1:] + assert not line.startswith(' ') + assert not line.endswith(' ') + assert '\t' not in line + assert indent <= len(stack) + stack = stack[:indent] + stack.append(line) + if indent == 0: + standalone.add(line) + else: + pairs.append((stack[indent - 1], line)) +except EOFError: + pass + +tree = {} +retree = {} +for parent, child in pairs: + if parent == child: + continue + if child in retree: + if retree[child] == parent: + continue + print('%s appears in the tree twice' % child, file = sys.stderr) + if parent in retree: + exit(1) + print('reversing with parent %s\n' % parent, file = sys.stderr) + (parent, child) = (child, parent) + if parent in tree: + tree[parent].append(child) + else: + tree[parent] = [child] + retree[child] = parent + +forest = {} +printed = {} +def printtree(this_tree, node, root, indent = ''): + if node in forest: + subtree = forest[node] + del forest[node] + this_tree.extend([(indent + subnode) for subnode in subtree]) + return + if node in printed: + if indent: + this_tree.append(indent + node) + return + this_tree.append(indent + node) + printed[node] = root + indent = indent + '\t' + if node in tree: + for child in sorted(tree[node]): + if child != root: + printtree(this_tree, child, root, indent) +defered = [] +for root in sorted(standalone): + if root in tree: + mytree = [] + printtree(mytree, root, root) + forest[root] = mytree + else: + defered.append(root) + +for tree in sorted(forest): + for line in forest[tree]: + print(line) +for stub in sorted(defered): + if stub not in printed: + print(stub) -- cgit v1.2.3-70-g09d2