Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for setfacl #639

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 92 additions & 0 deletions completions/setfacl
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
# setfacl(1) completion -*- shell-script -*-

_comp_cmd_setfacl()
{
local cur prev words cword split
# Don't treat user:group as separate words.
_init_completion -s -n : || return

if (( cword >= 2 )); then
local word
for word in "${words[@]:1:cword - 1}"; do
if [[ "$word" == '--' ]]; then
_filedir
return 0
fi
done
fi

case "$prev" in
--restore)
_filedir
return 0
;;

-m|--modify|-x|--remove|--set)
local other_rules prefix_default mycur
other_rules="${cur%"${cur##*,}"}"
cur="${cur##*,}"
if [[ $cur = d:* || $cur = default:* ]]; then
prefix_default=${cur%%"${cur#*:}"}
cur="${cur#*:}"
else
prefix_default=
fi
mycur="${cur##*:}"
if [[ $cur == *:*:*:* ]]; then
return
elif [[ $cur == *:*:* || $cur == [mo]*:* ]]; then
local opts
opts='- r w x X rw rx rX wx wX rwx rwX'
COMPREPLY=( $( compgen -S ',' -W "$opts" -- "$mycur" ) )
elif [[ $cur == u*:* ]]; then
local IFS
IFS=$'\n'
COMPREPLY=( $( compgen -u -S ':' -- "$mycur" ) )
elif [[ $cur == g*:* ]]; then
local IFS
IFS=$'\n'
COMPREPLY=( $( compgen -g -S ':' -- "$mycur" ) )
else
local prefixes
prefixes='user: group: mask: other:'
if [[ -z $prefix_default ]]; then
prefixes+=' default:'
fi
COMPREPLY=( $( compgen -W "$prefixes" -- "$mycur" ) )
fi
if [[ $cur != *:* && -z $prefix_default && "$other_rules" && ${#COMPREPLY[@]} -eq 1 ]]; then
COMPREPLY=("${other_rules##*:}${COMPREPLY[0]}")
fi
Comment on lines +58 to +60
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't checked the actual behavior, but I guess this has the same problem as #913 (comment) when bind 'set show-all-if-ambiguous on' is set.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This probably wouldn't have been picked up by the setfacl team, and you'd know better than I how to fix it.

Copy link
Collaborator

@akinomyoga akinomyoga Aug 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no robust way to make the displayed list compact. You'll need to always prefix the other_rules in the same way as PR #913. For example,

Suggested change
if [[ $cur != *:* && -z $prefix_default && "$other_rules" && ${#COMPREPLY[@]} -eq 1 ]]; then
COMPREPLY=("${other_rules##*:}${COMPREPLY[0]}")
fi
if [[ $cur != *:* && -z $prefix_default && "$other_rules" ]]; then
local i
for i in "${!COMPREPLY[@]}"; do
COMPREPLY[i]=${other_rules##*:}${COMPREPLY[i]}
done
fi

But I haven't tried to understand the part [[ $cur != *:* && -z $prefix_default ]], so it might not result in an expected result. Could you explain the condition [[ $cur != *:* && -z $prefix_default ]]? OK, I think I now understand it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re #913:

I'm not sure why the original only prepended the prefix back when there was only one completion, so I'm worried I'm missing something.

My understanding was that omitting the prefix when there are multiple candidates makes the list more concise, thus easier to visually scan & less likely to cause pagination. It also provides the ability to create richer results, as demonstrated in this article.

Without your suggestion the behaviour is like this:

roy@RoyBook:~$ setfacl --set user:w
whoopsie:  www-data:
roy@RoyBook:~$ setfacl --set user:whoopsie:rw
rw,   rwx,  rwX,
roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,group:a
adm:            audio:          avahi:          avahi-autoipd:
roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,group:adm:
-,    r,    rw,   rwx,  rwX,  rx,   rX,   w,    wx,   wX,   x,    X,
roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,group:adm:rw,
default:  group:    mask:     other:    user:
roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,group:adm:rw,other:
-,    r,    rw,   rwx,  rwX,  rx,   rX,   w,    wx,   wX,   x,    X,
roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,group:adm:rw,other:r

With it, the previous definition's mode is prepended to the next definition, which is a drop in readability:

roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,
rwX,default:  rwX,group:    rwX,mask:     rwX,other:    rwX,user:
roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,group:a
adm:            audio:          avahi:          avahi-autoipd:
roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,group:adm:
-,    r,    rw,   rwx,  rwX,  rx,   rX,   w,    wx,   wX,   x,    X,
roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,group:adm:rw,
rw,default:  rw,group:    rw,mask:     rw,other:    rw,user:

I tried to replicate the prefix loss per the last snippet of your comment, but it did not seem to occur. Perhaps this function is not affected due to the slightly different behviour around colons?

roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,group:avahi
avahi:          avahi-autoipd:
roy@RoyBook:~$ setfacl --set user:whoopsie:rwX,group:av<TAB>

[[ $COMPREPLY == *[:,] ]] && compopt -o nospace
return 0
;;

-M|--modify-file|-X|--remove-file|--set-file)
_filedir
return 0
;;

esac

$split && return 0

if [[ "$cur" == -* || $cword -eq 1 ]]; then
local opts
opts='--modify-file= --modify --remove-file= --remove --set-file= --set
--remove-all --remove-default --no-mask --mask --default --test
--recursive --logical --physical --'
if [[ ${#words[@]} -eq 2 ]]; then
opts+=' --version --help --restore='
elif [[ ${#words[@]} -eq 3 && "$prev" == --test ]]; then
opts+=' --restore='
fi
COMPREPLY=( $( compgen -W "$opts" -- "$cur" ) )
[[ $COMPREPLY == *= ]] && compopt -o nospace
else
_filedir
fi
} &&
complete -F _comp_cmd_setfacl setfacl

# ex: ts=4 sw=4 et filetype=sh