Skip to content

Commit db8d3ee

Browse files
committed
mount, umount: Add linux-specific completions.
This linux-specific completion won't parse /etc/fstab as a lot of people including myself find it useless. And there is no reliable way to guess what user wants to mount. Some examples of what is ok for mount: $ mount /home $ mount /dev/sda1 /home $ mount file.iso /media/iso -o loop $ mount LABEL=mydisk /media/disk It is more sane to provide just filenames completion for mount.
1 parent 43e8e2b commit db8d3ee

6 files changed

Lines changed: 373 additions & 106 deletions

File tree

completions/.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ stream
150150
tightvncviewer
151151
tracepath6
152152
typeset
153-
umount
154153
vgcfgbackup
155154
vgcfgrestore
156155
vgchange

completions/Makefile.am

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ bashcomp_DATA = a2x \
187187
mmsitepass \
188188
monodevelop \
189189
mount \
190+
mount.linux \
190191
mplayer \
191192
msynctool \
192193
mtx \
@@ -289,6 +290,8 @@ bashcomp_DATA = a2x \
289290
tcpnice \
290291
tracepath \
291292
tune2fs \
293+
umount \
294+
umount.linux \
292295
unace \
293296
unpack200 \
294297
unrar \
@@ -483,7 +486,6 @@ CLEANFILES = \
483486
tightvncviewer \
484487
tracepath6 \
485488
typeset \
486-
umount \
487489
vgcfgbackup \
488490
vgcfgrestore \
489491
vgchange \
@@ -660,10 +662,6 @@ symlinks:
660662
rm -f $(targetdir)/$$file && \
661663
$(LN_S) mcrypt $(targetdir)/$$file ; \
662664
done
663-
for file in umount ; do \
664-
rm -f $(targetdir)/$$file && \
665-
$(LN_S) mount $(targetdir)/$$file ; \
666-
done
667665
for file in mplayer2 mencoder gmplayer kplayer ; do \
668666
rm -f $(targetdir)/$$file && \
669667
$(LN_S) mplayer $(targetdir)/$$file ; \

completions/mount

Lines changed: 7 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,16 @@
11
# mount(8) completion -*- shell-script -*-
2+
3+
if [[ $OSTYPE == *linux* ]]; then
4+
. "$BASH_SOURCE.linux"
5+
return
6+
fi
7+
28
# This will pull a list of possible mounts out of
39
# /etc/{,v}fstab, unless the word being completed contains a ':', which
410
# would indicate the specification of an NFS server. In that case, we
511
# query the server for a list of all available exports and complete on
612
# that instead.
713
#
8-
9-
# Just like COMPREPLY=(`compgen -W "${COMPREPLY[*]}" -- "$cur"`), only better!
10-
#
11-
# This will correctly escape special characters in COMPREPLY.
12-
_reply_compgen_array()
13-
{
14-
# Create the argument for compgen -W by escaping twice.
15-
#
16-
# One round of escape is because we want to reply with escaped arguments. A
17-
# second round is required because compgen -W will helpfully expand it's
18-
# argument.
19-
local i wlist
20-
for i in ${!COMPREPLY[*]}; do
21-
local q=$(quote "$(printf %q "${COMPREPLY[$i]}")")
22-
wlist+=$q$'\n'
23-
done
24-
25-
# We also have to add another round of escaping to $cur.
26-
local ecur="$cur"
27-
ecur="${ecur//\\/\\\\}"
28-
ecur="${ecur//\'/\'}"
29-
30-
# Actually generate completions.
31-
local oldifs=$IFS
32-
IFS=$'\n' eval 'COMPREPLY=(`compgen -W "$wlist" -- "${ecur}"`)'
33-
IFS=$oldifs
34-
}
35-
36-
# Unescape strings in the linux fstab(5) format (with octal escapes).
37-
__linux_fstab_unescape() {
38-
eval $1="'${!1//\'/\047}'"
39-
eval $1="'${!1/%\\/\\\\}'"
40-
eval "$1=$'${!1}'"
41-
}
42-
43-
# Complete linux fstab entries.
44-
#
45-
# Reads a file from stdin in the linux fstab(5) format; as used by /etc/fstab
46-
# and /proc/mounts.
47-
_linux_fstab()
48-
{
49-
COMPREPLY=()
50-
51-
# Read and unescape values into COMPREPLY
52-
local fs_spec fs_file fs_other
53-
local oldifs="$IFS"
54-
while read -r fs_spec fs_file fs_other; do
55-
if [[ $fs_spec = [#]* ]]; then continue; fi
56-
if [[ $1 == -L ]]; then
57-
local fs_label=${fs_spec/#LABEL=}
58-
if [[ $fs_label != "$fs_spec" ]]; then
59-
__linux_fstab_unescape fs_label
60-
IFS=$'\0'
61-
COMPREPLY+=("$fs_label")
62-
IFS=$oldifs
63-
fi
64-
else
65-
__linux_fstab_unescape fs_spec
66-
__linux_fstab_unescape fs_file
67-
IFS=$'\0'
68-
[[ $fs_spec = */* ]] && COMPREPLY+=("$fs_spec")
69-
[[ $fs_file = */* ]] && COMPREPLY+=("$fs_file")
70-
IFS=$oldifs
71-
fi
72-
done
73-
74-
_reply_compgen_array
75-
}
76-
7714
_mount()
7815
{
7916
local cur prev words cword
@@ -116,39 +53,9 @@ _mount()
11653
# probably Cygwin
11754
COMPREPLY=( $( compgen -W "$( mount | awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' )" -- "$cur" ) )
11855
else
119-
# probably Linux
120-
if [[ $prev == -L ]]; then
121-
_linux_fstab -L < /etc/fstab
122-
elif [[ $prev == -U ]]; then
123-
COMPREPLY=( $( compgen -W '$(sed -ne "s/^[[:space:]]*UUID=\([^[:space:]]*\).*/\1/p" /etc/fstab )' -- "$cur" ) )
124-
else
125-
_linux_fstab < /etc/fstab
126-
fi
56+
COMPREPLY=( $( compgen -W "$( awk '! /^[ \t]*#/ {if ($3 ~ /\//) print $3}' /etc/fstab )" -- "$cur" ) )
12757
fi
128-
129-
return 0
13058
} &&
13159
complete -F _mount -o default -o dirnames mount
13260

133-
# umount(8) completion. This relies on the mount point being the third
134-
# space-delimited field in the output of mount(8)
135-
#
136-
_umount()
137-
{
138-
local cur prev words cword
139-
_init_completion || return
140-
141-
if [[ $OSTYPE == *linux* && -r /proc/mounts ]]; then
142-
# Linux /proc/mounts is properly quoted. This is important when
143-
# unmounting usb devices with pretty names.
144-
_linux_fstab < /proc/mounts
145-
else
146-
local IFS=$'\n'
147-
COMPREPLY=( $( compgen -W '$( mount | cut -d" " -f 3 )' -- "$cur" ) )
148-
fi
149-
150-
return 0
151-
} &&
152-
complete -F _umount -o dirnames umount
153-
15461
# ex: ts=4 sw=4 et filetype=sh

completions/mount.linux

Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
# mount(8) completion -*- shell-script -*-
2+
3+
_mount()
4+
{
5+
local cur prev words cword
6+
_init_completion -n =: || return
7+
8+
local split=false
9+
case "$prev" in
10+
-t|--types)
11+
# find /lib/modules/$(uname -r)/ -type f -path '*/fs/*.ko' -printf '%f\n' | cut -d. -f1
12+
# FIXME: no<fstype>
13+
if [[ "$cur" == ?*,* ]]; then
14+
prev="${cur%,*}"
15+
cur="${cur##*,}"
16+
split=true
17+
fi
18+
COMPREPLY=( $(compgen -W 'auto adfs affs autofs btrfs cifs coda
19+
cramfs debugfs devpts efs ext2 ext3 ext4 fuse hfs hfsplus hpfs
20+
iso9660 jfs minix msdos ncpfs nfs nfs4 ntfs ntfs-3g proc qnx4
21+
ramfs reiserfs romfs squashfs smbfs sysv tmpfs ubifs udf ufs
22+
umsdos usbfs vfat xfs' -- "$cur") )
23+
_fstypes
24+
$split && COMPREPLY=( ${COMPREPLY[@]/#/$prev,} )
25+
return
26+
;;
27+
--bind|-B|--rbind|-R)
28+
_filedir -d
29+
return
30+
;;
31+
-p|--pass-fd)
32+
COMPREPLY=( $(compgen -W '{0..9}') )
33+
compopt -o nospace
34+
return
35+
;;
36+
-L)
37+
COMPREPLY=( $( cd "/dev/disk/by-label/" 2>/dev/null || return; \
38+
compgen -f -- "$cur" ) )
39+
return
40+
;;
41+
-U)
42+
COMPREPLY=( $( cd "/dev/disk/by-uuid/" 2>/dev/null || return; \
43+
compgen -f -- "$cur" ) )
44+
return
45+
;;
46+
-O|--test-opts)
47+
# argument required but no completions available
48+
return
49+
;;
50+
-o|--options)
51+
local fstype=auto # default fstype
52+
for (( i=${#words[@]}-1; i>0; i-- )); do
53+
if [[ "${words[i]}" == -@(t|-types)* ]]; then
54+
if [[ "${words[i]}" == *=* ]]; then
55+
[[ "${words[i]}" == ?*,* ]] && break
56+
fstype="${words[i]#-*=}"
57+
else
58+
[[ "${words[i+1]}" == ?*,* ]] && break
59+
fstype="${words[i+1]}"
60+
fi
61+
break
62+
fi
63+
done
64+
# no<fstype> is not a real fstype, reset to "auto"
65+
[[ "$fstype" == no?* ]] && fstype=auto
66+
# split options list
67+
if [[ "$cur" == ?*,* ]]; then
68+
prev="${cur%,*}"
69+
cur="${cur##*,}"
70+
split=true
71+
fi
72+
# no completion if $cur is opt=smth
73+
[[ "$cur" == *=* ]] && return
74+
# mount options
75+
COMPREPLY=( $(compgen -W 'loop async {,no}atime {,no}auto
76+
{,fs,def,root}context= defaults {,no}dev {,no}diratime dirsync
77+
{,no}exec group {,no}iversion {,no}mand _netdev nofail
78+
{,no}relatime {,no}strictatime {,no}suid owner remount ro rw
79+
sync {,no}user users' -- "$cur") )
80+
case "$fstype" in
81+
adfs|auto)
82+
COMPREPLY+=( $(compgen -W 'uid= gid= {own,oth}mask=' -- \
83+
"$cur") )
84+
;;&
85+
affs|auto)
86+
COMPREPLY+=( $(compgen -W '{u,g}id= set{u,g}id= mode= protect
87+
usemp verbose prefix= volume= reserved= root= bs=
88+
{,no,usr,grp}quota' -- "$cur") )
89+
;;&
90+
btrfs|auto)
91+
COMPREPLY+=( $(compgen -W 'degraded subvol= subvolid= device=
92+
nodatasum nodatacow nobarrier max_inline= alloc_start=
93+
thread_pool= compress= compress-force= ssd noacl notreelog
94+
flushoncommit metadata_ratio= space_cache clear_cache
95+
user_subvol_rm_allowed autodefrag inode_cache' -- "$cur") )
96+
;;&
97+
cifs|auto)
98+
COMPREPLY+=( $(compgen -W 'user= password= credentials= {u,g}id=
99+
force{u,g}id port= servern= netbiosname= {file,dir}_mode=
100+
ip= domain= guest iocharset ro rw {,no}setuids {,no,dyn}perm
101+
directio {,no}mapchars {,no}intr hard soft noacl nocase sec=
102+
nobrl sfu {,no}serverino nounix nouser_xattr {r,w}size=' \
103+
-- "$cur") )
104+
;;&
105+
ext[2-4]|auto)
106+
COMPREPLY+=( $(compgen -W '{,no}acl bsddf minixdf check= debug
107+
errors= {,no}grpid {bsd,sysv}groups {,no,usr,grp}quota
108+
nobh nouid32 oldalloc orlov res{u,g}id= sb=
109+
{,no}user_xattr' -- "$cur") )
110+
;;&
111+
ext[34]|auto)
112+
COMPREPLY+=( $(compgen -W 'journal= journal_dev= norecovery
113+
noload data= barrier= commit=' -- "$cur") )
114+
;;&
115+
ext4|auto)
116+
COMPREPLY+=( $(compgen -W 'journal_checksum journal_async_commit
117+
nobarrier inode_readahead= stripe= {,no}delalloc abort
118+
{max,min}_batch_time= journal_ioprio= {,no}auto_da_alloc
119+
{,no}discard nouid32 resize {,no}block_validity
120+
dioread_{,no}lock i_version' -- "$cur") )
121+
;;&
122+
msdos|umsdos|vfat|auto)
123+
COMPREPLY+=( $(compgen -W 'blocksize= {u,g}id= {u,d,f}mask=
124+
allow_utime= check= codepage= conv= cvf_format= cvf_option=
125+
debug fat= iocharset= tz= quiet showexec sys_immutable flush
126+
usefree {,no}dots dotsOK=' -- "$cur") )
127+
;;&
128+
vfat|auto)
129+
COMPREPLY+=( $(compgen -W 'uni_xlate posix nonumtail utf8
130+
shortname=' -- "$cur") )
131+
;;&
132+
iso9660|auto)
133+
COMPREPLY+=( $(compgen -W 'norock nojoliet check= {u,g}id= map=
134+
mode= unhide block= conv= cruft session= sbsector=
135+
iocharset= utf8' -- "$cur") )
136+
;;&
137+
jfs|auto)
138+
COMPREPLY+=( $(compgen -W 'iocharset= resize= {,no}integrity
139+
errors= {,no,usr,grp}quota' -- "$cur") )
140+
;;&
141+
ntfs-3g)
142+
COMPREPLY+=( $(compgen -W '{u,g}id= {u,f,d}mask= usermapping=
143+
permissions inherit ro locale= force {,no}recover
144+
ignore_case remove_hiberfile {,no,rel}atime show_sys_files
145+
hide_{hid,dot}_files windows_names allow_other max_read=
146+
silent no_def_opts streams_interface= user_xattr efs_raw
147+
{,no}compression debug no_detach' -- "$cur") )
148+
;;&
149+
proc|auto)
150+
COMPREPLY+=( $(compgen -W '{u,g}id=' -- "$cur") )
151+
;;&
152+
reiserfs|auto)
153+
COMPREPLY+=( $(compgen -W 'conv hash= {,no_un}hashed_relocation
154+
noborder nolog notail replayonly resize= user_xattr acl
155+
barrier=' -- "$cur") )
156+
;;&
157+
tmpfs|auto)
158+
COMPREPLY+=( $(compgen -W 'size= nr_blocks= nr_inodes= mode=
159+
{u,g}id= mpol=' -- "$cur") )
160+
;;&
161+
udf|auto)
162+
COMPREPLY+=( $(compgen -W '{u,g}id= umask= unhide undelete
163+
nostrict iocharset bs= novrs session= anchor= volume=
164+
partition= lastblock= fileset= rootdir=' -- "$cur") )
165+
;;&
166+
usbfs|auto)
167+
COMPREPLY+=( $(compgen -W 'dev{u,g}id= devmode= bus{u,g}id=
168+
busmode= list{u,g}id= listmode=' -- "$cur") )
169+
;;&
170+
xfs|auto)
171+
COMPREPLY+=( $(compgen -W 'allocsize= {,no}attr2 barrier dmapi
172+
{,no}grpid {bsd,sysv}groups ihashsize= {,no}ikeep inode64
173+
{,no}largeio logbufs= logbsize= logdev= rtdev= mtpt= noalign
174+
noatime norecovery nouuid osyncisosync {u,g,p}qnoenforce
175+
{,u,usr,g,grp,p,prj}quota sunit= swidth= swalloc' \
176+
-- "$cur") )
177+
;;&
178+
esac
179+
# COMP_WORDBREAKS is a real pain in the ass
180+
prev="${prev##*[$COMP_WORDBREAKS]}"
181+
$split && COMPREPLY=( ${COMPREPLY[@]/#/"$prev,"} )
182+
[[ $COMPREPLY == *= ]] && compopt -o nospace
183+
return
184+
;;
185+
esac
186+
187+
if [[ "$cur" == -* ]]; then
188+
COMPREPLY=( $( compgen -W '-V --version -h --help -v --verbose -a --all
189+
-F --fork -f --fake -i --internal-only -l -n --no-mtab
190+
--no-canonicalize -p --pass-fd -s -r --read-only -w --rw -L -U
191+
-t --types -O --test-opts -o --options -B --bind -R --rbind
192+
-M --move' -- "$cur" ) )
193+
[[ $COMPREPLY ]] && return
194+
fi
195+
196+
[[ "$cur" == \\ ]] && cur="/"
197+
198+
local sm host
199+
200+
if [[ "$cur" == *:* ]]; then
201+
for sm in "$(type -P showmount)" {,/usr}/{,s}bin/showmount; do
202+
[[ -x $sm ]] || continue
203+
COMPREPLY=( $( compgen -W "$( "$sm" -e ${cur%%:*} | \
204+
awk 'NR>1 {print $1}' )" -- "${cur#*:}" ) )
205+
return 0
206+
done
207+
fi
208+
209+
if [[ "$cur" == //* ]]; then
210+
host=${cur#//}
211+
host=${host%%/*}
212+
if [[ -n $host ]]; then
213+
COMPREPLY=( $( compgen -P "//$host" -W \
214+
"$( smbclient -d 0 -NL $host 2>/dev/null |
215+
sed -ne '/^['"$'\t '"']*Sharename/,/^$/p' |
216+
sed -ne '3,$s|^[^A-Za-z]*\([^'"$'\t '"']*\).*$|/\1|p' )" \
217+
-- "${cur#//$host}" ) )
218+
fi
219+
fi
220+
221+
_filedir
222+
} &&
223+
complete -F _mount mount
224+
225+
# ex: ts=4 sw=4 et filetype=sh

0 commit comments

Comments
 (0)