# Advanced bash completion for socat (supports address types and their options)

_socat() {
	local cur prev words cword split
	_init_completion -s || return

	local common_options="-V -h -? -hh -?? -hhh -??? -d -d0 -dd -d2 -ddd -d3 -dddd -d4 -D --experimental -ly -lf -ls -lp -lu -lm -lh -v -x -r -R -b -s -S -t -T -u -U -g -L -W -4 -6 -0 --statistics"

	local address_types="
		ABSTRACT-CLIENT ABSTRACT-CONNECT ABSTRACT-LISTEN ABSTRACT-RECV
		ABSTRACT-RECVFROM ABSTRACT-SENDTO ACCEPT-FD CREATE
		DCCP-CONNECT DCCP-CONNECT4 DCCP-CONNECT6 DCCP-LISTEN
		DCCP-LISTEN4 DCCP-LISTEN6 EXEC FD GOPEN INTERFACE
		IP-DATAGRAM IP-RECV IP-RECVFROM IP-SENDTO IP4-DATAGRAM
		IP4-RECV IP4-RECVFROM IP4-SENDTO IP6-DATAGRAM IP6-RECV
		IP6-RECVFROM IP6-SENDTO OPEN OPENSSL OPENSSL-DTLS-CLIENT
		OPENSSL-DTLS-SERVER OPENSSL-LISTEN PIPE POSIXMQ
		POSIXMQ-BIDIRECTIONAL POSIXMQ-READ POSIXMQ-RECEIVE
		POSIXMQ-RECV POSIXMQ-SEND POSIXMQ-WRITE PROXY PTY
		READLINE SCTP-CONNECT SCTP-CONNECT4 SCTP-CONNECT6
		SCTP-LISTEN SCTP-LISTEN4 SCTP-LISTEN6 SHELL
		SOCKET-CONNECT SOCKET-DATAGRAM SOCKET-LISTEN SOCKET-RECV
		SOCKET-RECVFROM SOCKET-SENDTO SOCKETPAIR SOCKS4 SOCKS4A
		SOCKS5-CONNECT SOCKS5-LISTEN STALL STDERR STDIN STDIO
		STDOUT SYSTEM TCP TCP-LISTEN TCP4 TCP4-LISTEN TCP6
		TCP6-LISTEN TEXT TUN UDP UDP-DATAGRAM UDP-LISTEN
		UDP-RECV UDP-RECVFROM UDP-SENDTO UDP4 UDP4-DATAGRAM
		UDP4-LISTEN UDP4-RECV UDP4-RECVFROM UDP4-SENDTO UDP6
		UDP6-DATAGRAM UDP6-LISTEN UDP6-RECV UDP6-RECVFROM
		UDP6-SENDTO UDPLITE-CONNECT UDPLITE-DATAGRAM UDPLITE-LISTEN
		UDPLITE-RECV UDPLITE-RECVFROM UDPLITE-SENDTO
		UDPLITE4-CONNECT UDPLITE4-DATAGRAM UDPLITE4-LISTEN
		UDPLITE4-RECV UDPLITE4-RECVFROM UDPLITE4-SENDTO
		UDPLITE6-CONNECT UDPLITE6-DATAGRAM UDPLITE6-LISTEN
		UDPLITE6-RECV UDPLITE6-RECVFROM UDPLITE6-SENDTO
		UNIX-CLIENT UNIX-CONNECT UNIX-LISTEN UNIX-RECV
		UNIX-RECVFROM UNIX-SENDTO VSOCK-CONNECT VSOCK-LISTEN
	"

	local common_addr_opts="
		accept-timeout append bind broadcast cfmakeraw chroot cipher
		commonname connect-timeout cr creat crnl ctty dccp-set-ccid
		dccp-set-sid egd fdin fdout flock-ex flock-ex-nb flock-sh
		flock-sh-nb fork forever group history ignoreeof interval
		ip-add-membership ip-add-source-membership ip-multicast-if
		ip-multicast-loop ip-multicast-ttl ip-pktinfo ip-recverr
		ip-recvopts ip-recvtos ip-recvttl ip-transparent
		ipv6-join-group ipv6-join-source-group ipv6only keepalive
		key link lock lowport max-children max-proto-version
		min-proto-version mode mss netnl noecho nofork nonblock
		openpty path pf pipes pty range raw rawer rcvbuf readbytes
		reuseaddr retry sctp-maxseg sctp-nodelay setgid setsid
		setuid sockspass socksport socksuser sourceport stderr su
		su-d tcpwrap ttl tun-device tun-name tun-type umask unlink
		unlink-close unlink-early unlink-late user verify wait-slave
	"

	if [[ "$cur" == -* ]]; then
		COMPREPLY=($(compgen -W "$common_options" -- "$cur"))
		return 0
	fi

	if [[ "$cur" == *","* ]]; then
		local before_comma="${cur%,*}"
		local after_comma="${cur##*,}"
		local matches=($(compgen -W "$common_addr_opts" -- "$after_comma"))
		if [[ ${#matches[@]} -gt 0 ]]; then
			COMPREPLY=($(for i in "${matches[@]}"; do echo "${before_comma},$i"; done))
		else
			COMPREPLY=($(for i in ${common_addr_opts}; do echo "${before_comma},$i"; done))
		fi
		return 0
	fi

	COMPREPLY=($(compgen -W "$address_types" -- "$cur"))
	return 0
}

complete -F _socat socat
