Skip to content

Commit d0e7097

Browse files
A Dynamic Collection of Shell Scripts with Educational Purpose
1 parent fe21d53 commit d0e7097

2 files changed

Lines changed: 206 additions & 79 deletions

File tree

scripts/ble-simple

Lines changed: 66 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -597,14 +597,32 @@ _cs_redraw() {
597597
colored="$_CS_BUFFER"
598598
fi
599599

600-
local _term_cols; _term_cols=$(tput cols 2>/dev/null || printf '80')
601-
local _prev_len=$(( _CS_PS1_LEN + ${#_CS_BUFFER} ))
600+
# local _term_cols; _term_cols=$(tput cols 2>/dev/null || printf '80')
601+
# local _prev_len=$(( _CS_PS1_LEN + ${#_CS_BUFFER} ))
602+
# local _prev_lines=$(( _prev_len / _term_cols ))
603+
604+
local _term_cols=$(( COLUMNS > 0 ? COLUMNS : 80 ))
605+
local _buf_visual="${_CS_BUFFER//\\/}"
606+
local _char_count
607+
_char_count=$(printf '%s' "$_buf_visual" | wc -m 2>/dev/null || printf '%s' "${#_buf_visual}")
608+
local _prev_len=$(( _CS_PS1_LEN + _char_count ))
602609
local _prev_lines=$(( _prev_len / _term_cols ))
610+
if (( _prev_lines > 0 )); then
611+
printf '\e[%dA' "$_prev_lines" >&2
612+
fi
613+
printf '\r\e[2K%s%s\e[K' "$_CS_PS1_LAST" "$colored" >&2
614+
printf '\r\e[%dG' "$(( ( _CS_PS1_LEN + _CS_POS ) % _term_cols + 1 ))" >&2
603615

616+
local _prev_lines=$(( _prev_len / _term_cols ))
617+
printf 'DEBUG redraw buf_len=%s pos=%s visual_len=%s\n' \
618+
"${#_CS_BUFFER}" "$_CS_POS" "$_char_count" >> "${TMPDIR}/cs_debug.log"
604619
if (( _prev_lines > 0 )); then
605620
printf '\e[%dA' "$_prev_lines" >&2
606621
fi
607622

623+
printf 'DEBUG term_cols=%s buf_visual="%s" char_count=%s wide_count=%s prev_len=%s prev_lines=%s\n' \
624+
"$_term_cols" "${_buf_visual:0:30}" "$_char_count" "$_wide_count" "$_prev_len" "$_prev_lines" >> "${TMPDIR}/cs_debug.log"
625+
608626
if [[ -n "$TERMUX_VERSION" ]]; then
609627
local _ghost_inline=""
610628
local _ghost_len=0
@@ -624,6 +642,7 @@ _cs_redraw() {
624642
fi
625643
fi
626644
fi
645+
printf 'DEBUG buf_len=%s colored_len=%s\n' "${#_CS_BUFFER}" "${#colored}" >> "${TMPDIR}/cs_debug.log"
627646
printf '\r\e[J%s%s%s' "$_CS_PS1_LAST" "$colored" "$_ghost_inline" >&2
628647
local _cursor_target=$(( ( _CS_PS1_LEN + _CS_POS ) % _term_cols + 1 ))
629648
local _total_drawn=$(( _CS_PS1_LEN + ${#_CS_BUFFER} + _ghost_len ))
@@ -696,77 +715,34 @@ _cs_do_shift_tab() {
696715
_cs_redraw
697716
}
698717

699-
_cs_quote_completion() {
700-
local completion="$1"
701-
if [[ "$completion" == *' '* ]]; then
702-
completion="${completion/#\~/$HOME}"
703-
completion="${completion//\"/}"
704-
# Trailing slash será preservada dentro das aspas
705-
completion="\"${completion}\""
706-
fi
707-
printf '%s' "$completion"
708-
}
718+
# _cs_quote_completion() {
719+
# local completion="$1"
720+
# if [[ "$completion" == *' '* ]]; then
721+
# completion="${completion/#\~/$HOME}"
722+
# completion="${completion//\"/}"
723+
# # Trailing slash será preservada dentro das aspas
724+
# completion="\"${completion}\""
725+
# fi
726+
# printf '%s' "$completion"
727+
# }
709728

710-
f_cs_quote_completion() {
729+
_cs_quote_completion() {
711730
local completion="$1"
712731
local trailing_slash=""
713732
[[ "$completion" == */ ]] && trailing_slash="/" && completion="${completion%/}"
714733

715-
# Escapa sempre com \ se contém espaço ou qualquer caractere não-seguro
716-
# Inclui caracteres unicode problemáticos via verificação de espaço e ASCII especial
717-
local needs_escape=0
718-
[[ "$completion" == *' '* ]] && needs_escape=1
719-
[[ "$completion" == *"'"* ]] && needs_escape=1
720-
[[ "$completion" == *'"'* ]] && needs_escape=1
721-
[[ "$completion" == *'('* ]] && needs_escape=1
722-
[[ "$completion" == *')'* ]] && needs_escape=1
723-
[[ "$completion" == *'['* ]] && needs_escape=1
724-
[[ "$completion" == *']'* ]] && needs_escape=1
725-
[[ "$completion" == *'{'* ]] && needs_escape=1
726-
[[ "$completion" == *'}'* ]] && needs_escape=1
727-
[[ "$completion" == *'&'* ]] && needs_escape=1
728-
[[ "$completion" == *';'* ]] && needs_escape=1
729-
[[ "$completion" == *'!'* ]] && needs_escape=1
730-
[[ "$completion" == *'#'* ]] && needs_escape=1
731-
[[ "$completion" == *'$'* ]] && needs_escape=1
732-
[[ "$completion" == *'`'* ]] && needs_escape=1
733-
[[ "$completion" == *'|'* ]] && needs_escape=1
734-
[[ "$completion" == *'<'* ]] && needs_escape=1
735-
[[ "$completion" == *'>'* ]] && needs_escape=1
736-
[[ "$completion" == *','* ]] && needs_escape=1
737-
[[ "$completion" == *'~'* ]] && needs_escape=1
738-
[[ "$completion" == *'*'* ]] && needs_escape=1
739-
[[ "$completion" == *'?'* ]] && needs_escape=1
740-
[[ "$completion" == *'\'* ]] && needs_escape=1
741-
742-
if (( needs_escape )); then
743-
# Escapa \ primeiro para não duplo-escapar
744-
completion="${completion//\\/\\\\}"
745-
completion="${completion// /\\ }"
746-
completion="${completion//\'/\\\'}"
747-
completion="${completion//\"/\\\"}"
748-
completion="${completion//(/\\(}"
749-
completion="${completion//)/\\)}"
750-
completion="${completion//[/\\[}"
751-
completion="${completion//]/\\]}"
752-
completion="${completion//\{/\\\{}"
753-
completion="${completion//\}/\\\}}"
754-
completion="${completion//&/\\&}"
755-
completion="${completion//;/\\;}"
756-
completion="${completion//!/\\!}"
757-
completion="${completion//#/\\#}"
758-
completion="${completion//\$/\\\$}"
759-
completion="${completion//\`/\\\`}"
760-
completion="${completion//|/\\|}"
761-
completion="${completion//</\\<}"
762-
completion="${completion//>/\\>}"
763-
completion="${completion//,/\\,}"
764-
completion="${completion//~/\\~}"
765-
completion="${completion//\*/\\*}"
766-
completion="${completion//\?/\\?}"
767-
fi
734+
local result="" i c
735+
local safe_chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_.-+@=%^:~//'
736+
for (( i=0; i<${#completion}; i++ )); do
737+
c="${completion:$i:1}"
738+
if [[ "$safe_chars" == *"$c"* ]]; then
739+
result+="$c"
740+
else
741+
result+="\\${c}"
742+
fi
743+
done
768744

769-
printf '%s' "${completion}${trailing_slash}"
745+
printf '%s' "${result}${trailing_slash}"
770746
}
771747

772748
_cs_do_tab() {
@@ -820,7 +796,6 @@ _cs_do_tab() {
820796
fi
821797
(( word_start-- ))
822798
done
823-
printf 'DEBUG word_start=%s cur="%s"\n' "$word_start" "${line:$word_start:$((point - word_start))}" >> "${TMPDIR}/cs_debug.log"
824799

825800
local cur="${line:$word_start:$((point - word_start))}"
826801
# Normaliza cur: remove aspas externas e backslashes de escape
@@ -867,6 +842,12 @@ _cs_do_tab() {
867842
_glob_matches+=("$_f")
868843
done
869844
eval "$_shopt_save"
845+
printf 'DEBUG glob_matches="%s"\n' "${_glob_matches[*]}" >> "${TMPDIR}/cs_debug.log"
846+
printf 'DEBUG glob_n="%s"\n' "${#_glob_matches[@]}" >> "${TMPDIR}/cs_debug.log"
847+
if (( ${#_glob_matches[@]} == 1 )); then
848+
printf 'DEBUG single_match="%s"\n' "${_glob_matches[0]}" >> "${TMPDIR}/cs_debug.log"
849+
printf 'DEBUG after_quote="%s"\n' "$(_cs_quote_completion "${_glob_matches[0]}")" >> "${TMPDIR}/cs_debug.log"
850+
fi
870851
if (( ${#_glob_matches[@]} == 0 )); then
871852
printf '\a' >&2; _cs_redraw; return
872853
fi
@@ -881,7 +862,12 @@ _cs_do_tab() {
881862
local _suffix=""
882863
[[ -d "${_clean/#\~/$HOME}" && "$_clean" != */ ]] && _suffix="/"
883864
_CS_BUFFER="${line:0:$word_start}${_completion}${_suffix}${after}"
884-
_CS_POS=$(( word_start + ${#_completion} + ${#_suffix} ))
865+
local _completion_visual="${_completion//\\/}"
866+
local _completion_visual_len
867+
_completion_visual_len=$(printf '%s' "$_completion_visual" | wc -m 2>/dev/null || printf '%s' "${#_completion_visual}")
868+
_CS_POS=$(( word_start + _completion_visual_len + ${#_suffix} ))
869+
printf 'DEBUG final_buf="%s" final_pos=%s buf_len=%s\n' \
870+
"${_CS_BUFFER:0:50}" "$_CS_POS" "${#_CS_BUFFER}" >> "${TMPDIR}/cs_debug.log"
885871
_cs_tab_reset; _cs_redraw; return
886872
fi
887873
mapfile -t completions < <(printf '%s\n' "${_glob_matches[@]}" | sort -u)
@@ -987,7 +973,10 @@ _cs_do_tab() {
987973
local _suffix=""
988974
[[ -d "${_clean/#\~/$HOME}" && "$_clean" != */ ]] && _suffix="/"
989975
_CS_BUFFER="${line:0:$word_start}${_completion}${_suffix}${after}"
990-
_CS_POS=$(( word_start + ${#_completion} + ${#_suffix} ))
976+
local _completion_visual="${_completion//\\/}"
977+
local _completion_visual_len
978+
_completion_visual_len=$(printf '%s' "$_completion_visual" | wc -m 2>/dev/null || printf '%s' "${#_completion_visual}")
979+
_CS_POS=$(( word_start + _completion_visual_len + ${#_suffix} ))
991980
_cs_tab_reset; _cs_redraw; return
992981
else
993982
mapfile -t completions < <(printf '%s\n' "${_glob_matches[@]}" | sort -u)
@@ -1090,11 +1079,12 @@ _cs_do_tab() {
10901079
# _CS_POS=$(( word_start + ${#completion} + ${#suffix} ))
10911080
# _cs_tab_reset; _cs_redraw; return
10921081
# fi
1082+
1083+
printf 'DEBUG completion_raw="%s"\n' "${completions[0]}" >> "${TMPDIR}/cs_debug.log"
1084+
printf 'DEBUG completion_after_quote="%s"\n' "$(_cs_quote_completion "${completions[0]}")" >> "${TMPDIR}/cs_debug.log"
10931085

1094-
printf 'DEBUG before_n1 n=%s completions="%s"\n' "$n" "${completions[*]}" >> "${TMPDIR}/cs_debug.log"
10951086
if (( n == 1 )); then
10961087
local completion="${completions[0]}"
1097-
printf 'DEBUG n1 completion="%s" cur="%s" word_start=%s\n' "$completion" "$cur" "$word_start" >> "${TMPDIR}/cs_debug.log"
10981088
if [[ "${cur}" == ~* || "${line:0:$word_start}" == *~* ]]; then
10991089
completion="${completion/#$HOME/\~}"
11001090
fi
@@ -1163,7 +1153,10 @@ _cs_do_tab() {
11631153
local _suffix=""
11641154
[[ -d "${_clean/#\~/$HOME}" && "$_clean" != */ ]] && _suffix="/"
11651155
_CS_BUFFER="${line:0:$word_start}${_completion}${_suffix}${after}"
1166-
_CS_POS=$(( word_start + ${#_completion} + ${#_suffix} ))
1156+
local _completion_visual="${_completion//\\/}"
1157+
local _completion_visual_len
1158+
_completion_visual_len=$(printf '%s' "$_completion_visual" | wc -m 2>/dev/null || printf '%s' "${#_completion_visual}")
1159+
_CS_POS=$(( word_start + _completion_visual_len + ${#_suffix} ))
11671160
_cs_tab_reset; _cs_redraw; return
11681161
else
11691162
mapfile -t completions < <(printf '%s\n' "${_glob_matches[@]}" | sort -u)
@@ -1250,12 +1243,6 @@ _cs_do_tab() {
12501243
_CS_POS=$(( _CS_TAB_WORD_START + ${#_first_c} ))
12511244
_cs_redraw; return
12521245
fi
1253-
printf 'DEBUG cur_clean="%s" cur_expanded="%s"\n' "$cur_clean" "$cur_expanded" >> "${TMPDIR}/cs_debug.log"
1254-
printf 'DEBUG glob_pattern="%s"\n' "${cur_expanded}*" >> "${TMPDIR}/cs_debug.log"
1255-
for _f in "${cur_expanded}"*; do
1256-
printf 'DEBUG glob_match="%s"\n' "$_f" >> "${TMPDIR}/cs_debug.log"
1257-
done
1258-
printf 'DEBUG completions="%s" n=%s\n' "${completions[*]}" "${#completions[@]}" >> "${TMPDIR}/cs_debug.log"
12591246

12601247
_CS_TAB_COMPLETIONS=("${completions[@]}")
12611248
_CS_TAB_STATE=-1

scripts/sway-keepassxc-hide-show

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
#!/usr/bin/env bash
2+
# License: GPLv3
3+
# Credits: Felipe Facundes (adapted for KeePassXC)
4+
5+
# Match windows with "KeePassXC" in title AND app_id is null
6+
filter() {
7+
swaymsg -t get_tree | jq -r '.. | select(.name? != null) | select(.name? | test("KeePassXC")) | select(.app_id? == null) | .name'
8+
}
9+
10+
# Get the exact window title and escape special characters for Sway
11+
get_kp_title_escaped() {
12+
local title
13+
title=$(swaymsg -t get_tree | jq -r '.. | select(.name? != null) | select(.name? | test("KeePassXC")) | select(.app_id? == null) | .name' | head -1)
14+
# Escape [ and ] for Sway criteria
15+
title="${title//\[/\\[}"
16+
title="${title//\]/\\]}"
17+
echo "$title"
18+
}
19+
20+
# Get the con_id for the KeePassXC window
21+
get_kp_con_id() {
22+
swaymsg -t get_tree | jq -r '.. | select(.name? != null) | select(.name? | test("KeePassXC")) | select(.app_id? == null) | .id' | head -1
23+
}
24+
25+
# Get the floating state of the window
26+
get_floating_state() {
27+
local con_id="$1"
28+
swaymsg -t get_tree | jq -r ".. | select(.id? == $con_id) | .floating" 2>/dev/null
29+
}
30+
31+
help() {
32+
cat << EOF
33+
${0##*/} - Toggle KeePassXC visibility in Sway scratchpad
34+
35+
SYNOPSIS
36+
${0##*/} [OPTION]
37+
38+
DESCRIPTION
39+
This script manages a KeePassXC window in the Sway window manager.
40+
It toggles the visibility of KeePassXC between the scratchpad
41+
and the current workspace, preserving its original window state.
42+
43+
USAGE EXAMPLES
44+
${0##*/} # Normal toggle
45+
${0##*/} --debug # Show debug info
46+
47+
OPTIONS
48+
-h, --help Display this help message
49+
--debug Show debug information
50+
EOF
51+
exit 0
52+
}
53+
54+
[[ "$1" == "-h" || "$1" == "--help" ]] && help
55+
56+
DEBUG=false
57+
[[ "$1" == "--debug" ]] && DEBUG=true
58+
59+
$DEBUG && {
60+
echo "========== DEBUG INFO =========="
61+
echo "Filter output:"
62+
filter
63+
echo ""
64+
echo "Escaped title:"
65+
get_kp_title_escaped
66+
echo ""
67+
echo "Con ID:"
68+
get_kp_con_id
69+
echo ""
70+
}
71+
72+
# Check if KeePassXC window exists
73+
check_string=$(filter)
74+
75+
if [[ -z "$check_string" ]]; then
76+
$DEBUG && echo "Window not found, launching KeePassXC..."
77+
78+
# Launch KeePassXC
79+
keepassxc 2>/dev/null &
80+
81+
# Wait for the window to appear
82+
for i in {1..10}; do
83+
sleep 0.2
84+
check_string=$(filter)
85+
if [[ -n "$check_string" ]]; then
86+
break
87+
fi
88+
done
89+
90+
if [[ -n "$check_string" ]]; then
91+
kp_title=$(get_kp_title_escaped)
92+
swaymsg "[title=\"$kp_title\"]" move container to scratchpad
93+
echo "KeePassXC opened and moved to scratchpad."
94+
else
95+
echo "Failed to open KeePassXC window."
96+
exit 1
97+
fi
98+
fi
99+
100+
# Get the escaped window title and con_id
101+
kp_title=$(get_kp_title_escaped)
102+
con_id=$(get_kp_con_id)
103+
104+
$DEBUG && echo "Using title: $kp_title"
105+
$DEBUG && echo "Using con_id: $con_id"
106+
107+
# Save floating state BEFORE any operation
108+
floating_state="auto_off"
109+
if [[ -n "$con_id" && "$con_id" != "null" ]]; then
110+
floating_state=$(get_floating_state "$con_id")
111+
$DEBUG && echo "Current floating state: $floating_state"
112+
fi
113+
114+
# Toggle KeePassXC visibility
115+
if ! swaymsg "[title=\"$kp_title\"]" scratchpad show 2>/dev/null; then
116+
$DEBUG && echo "Window is visible, moving to scratchpad..."
117+
# Save state file to remember the floating state
118+
echo "$floating_state" > "/tmp/keepassxc_floating_state"
119+
swaymsg "[title=\"$kp_title\"]" move container to scratchpad
120+
else
121+
$DEBUG && echo "Window was in scratchpad, showing and restoring state..."
122+
123+
# Read saved floating state
124+
saved_state="auto_off"
125+
if [[ -f "/tmp/keepassxc_floating_state" ]]; then
126+
saved_state=$(cat "/tmp/keepassxc_floating_state")
127+
$DEBUG && echo "Saved floating state: $saved_state"
128+
fi
129+
130+
# If the window was not floating before, disable floating
131+
if [[ "$saved_state" == "auto_off" ]]; then
132+
$DEBUG && echo "Restoring to non-floating state..."
133+
# Wait a tiny bit for the window to appear
134+
sleep 0.05
135+
swaymsg "[title=\"$kp_title\"]" floating disable
136+
fi
137+
138+
# Focus the window
139+
swaymsg "[title=\"$kp_title\"]" focus
140+
fi

0 commit comments

Comments
 (0)