#!/usr/bin/env fish
#
# This file provides generic functions for generating specific completions for 
# hg, darcs and a few other vcs systems. It uses the fact that all these 
# systems have a somewhat uniform command line help mechanism.
#

function cap
	set res (echo $argv |cut -c 1|tr a-z A-Z)(echo $argv |cut -c 2-)
	echo $res
end

#
# Escapes the single quote (') character and removes trailing whitespace from $argv
#

function esc
	echo $argv | sed -e "s/\(['\\\]\)/\\\\\1/g" | sed -e 's/ *$//' | sed -e 's/     .*//'
end


#
# This function formats a list of completion information into a set of fish completions
#
# The first argument is the condition string, which will be copied to
# the resulting commandline verbatim
#
# Remaining arguments are tab separated lists of completion
# information. Each list contains four elements, the short switch, the
# long switch, the argument and the description.
#

function complete_from_list

	set condition $argv[1]
	set -e argv[1]

	for j in $argv
		set exploded (echo $j|tr \t \n)
		set short $exploded[1]
		set long $exploded[2]
		set arg $exploded[3]
		set desc (cap (esc $exploded[4]))

		set str

		switch $short
			case '-?'
				set str $str -s (printf "%s\n" $short|cut -c 2)
		end

		switch $long
			case '--?*'
				set str $str -l (printf "%s\n" $long|cut -c 3-)
		end

		switch $arg
			case '=DIRECTORY' ' dir'
				set str $str -x -a "'(__fish_complete_directories (commandline -ct))'"

			case '=COMMAND'
				set str $str -x -a "'(__fish_complete_command)'"

			case '=USERNAME' ' <user>'
				set str $str -x -a "'(__fish_complete_users)'"

			case '=FILENAME' '=FILE' ' <file>'
				set str $str -r

			case ' arg'
				set str $str -x

			case ' (*):'
				 set str $str -x -a \'(echo $arg| sed -e "s/ (\(.*\)):/\1/" |tr '/' ' ')\'

			case '?*'
				set str $str -x
				if not set -q unknown
					set -g unknown
				end
				if not contains $arg $unknown
					echo "Don't know how to handle arguments of type '$arg'" >&2
					set unknown $unknown $arg
				end
		end

		switch $desc
			case '?*'
				set str $str --description \'$desc\'
		end

		echo complete -c $cmd $condition $str

	end

end


function write_completions

	set -g cmd $argv[1]; or return 1

	echo "Making completions for $cmd" >&2


	echo '
#
# Completions for the '$cmd' command
# This file was autogenerated by the file make_vcs_completions.fish
# which is shipped with the fish source code.
#

#
# Completions from commandline
#
'
	set -e argv[1]

	while count $argv >/dev/null
		echo $argv[1]
		set -e argv[1]
	end


	eval "function cmd; $cmd \$argv; end"

	set -l cmd_str

	switch $cmd
		case svn

		function list_subcommand
			set cmd1 '\([^ ]*\)'
			set cmd2 '\([^,)]*\)'
			set cmdn '\(, \([^,)]*\)\|\)'
			set svn_re '^    *'$cmd1'\( ('$cmd2$cmdn$cmdn')\|\).*$'
			cmd help|sed -ne 's/'$svn_re'/\1\n\3\n\5\n\7/p'| grep .
		end

		function list_subcommand_help
			set short_exp '\(-.\|\)'
			set long_exp '\(--[^ =,]*\)'
			set arg_exp '\(\|[= ][^ ][^ ]*\)'
			set desc_exp '\([\t ]*:[\t ]*\|\)\([^ ].*[^.]\)'
			set re "^ *$short_exp  *$long_exp$arg_exp  *$desc_exp\(\|\\.\)\$"
			cmd help $argv | sed -n -e 's/'$re'/\1\t\2\t\3\t\5/p'
		end

		for i in (list_subcommand)

			set desc (cmd help $i|head -n 3| sed -e 's/usage:.*//'| tr \n \ | sed -e 's/[^:]*: *\(.*[^.]\)\(\|\\.\)$/\1/')
			set desc (esc $desc)
			set cmd_str $cmd_str "-a $i --description '$desc'"
		end

		case cvs

		function list_subcommand
			cmd --help-commands 2>| sed -n -e 's/^   *\([^ ][^ ]*\) .*$/\1/p'
		end

		set short_exp '\(-.\)'
		set arg_exp '\(\| [^ \t][^ \t]*\)'
		set desc_exp '\([\t ]*:[\t ]*\|\)\([^ ].*\)'
		set -g re '^[ \t]*'$short_exp$arg_exp'[ \t]*'$desc_exp'$'

		function list_subcommand_help
#'s/^[ \t]*\(-.\)[ \t]\([^- \t][^ \t]*\)*[ \t]*\([^-].*\)$/\1\t\2\t\3/p'

			cmd -H $argv 2>| sed -n -e 's/'$re'/\1\t\t\2\t\4/p'
		end

		echo '
#
# Global switches
#
'

		complete_from_list "-n '__fish_use_subcommand'" (cmd --help-options 2>| sed -n -e 's/'$re'/\1\t\t\2\t\4/p')

		set cmd_str_internal (cmd --help-commands 2>| sed -n -e 's/^  *\([^ ][^ ]*\)[\t ]*\([^ ].*\)$/\1\t\2/p')
		for i in $cmd_str_internal
			set exploded (echo $i|tr \t \n)
			set cmd_str $cmd_str "-a $exploded[1] --description '"(esc $exploded[2])"'"
		end

		case '*'

		function list_subcommand
			cmd help | sed -n -e 's/^  *\([^ ][^ ]*\) .*$/\1/p'
		end

		function list_subcommand_help
			set -l short_exp '\(-.\|\)\( [^ -][^ ]*\|\)'
			set -l long_exp '\(--[^ =,]*\)'
			set -l arg_exp '\(\|[= ][^ ][^ ]*\)'
			set -l desc_exp '\([\t ]*:[\t ]*\|\)\([^ ].*[^.]\)'
			set -l re "^ *$short_exp  *$long_exp$arg_exp  *$desc_exp\(\|\\.\)\$"

			cmd help $argv | sed -n -e 's/'$re'/\1\t\3\t\4\t\6/p'
		end

		set cmd_str (cmd help | sed -n -e 's/^  *\([^ ][^ ]*\)[\t ]*\([^ ].*[^.]\)\(\|\\.\)$/-a \1 --description \'\2\'/p')

	end

	echo '
#
# subcommands
#
'

	printf "complete -c $cmd -n '__fish_use_subcommand' -x %s\n" $cmd_str

	for i in (list_subcommand)

		echo '

#
# Completions for the \''$i'\' subcommand
#
'

		complete_from_list "-n 'contains \\'$i\\' (commandline -poc)'" (list_subcommand_help $i)
	end

	echo \n\n

end