summaryrefslogtreecommitdiff
path: root/zsh/termsupport.zsh
blob: d406fc6ce8a4b4ccdda50aa8257f342ad5f2b4eb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
function zsh_urlencode() {
	emulate -L zsh
	local -a opts
	zparseopts -D -E -a opts r m P

	local in_str="$@"
	local url_str=""
	local spaces_as_plus
	if [[ -z $opts[(r)-P] ]]; then spaces_as_plus=1; fi
	local str="$in_str"

	# URLs must use UTF-8 encoding; convert str to UTF-8 if required
	local encoding=$langinfo[CODESET]


	# Use LC_CTYPE=C to process text byte-by-byte
	local i byte ord LC_ALL=C
	export LC_ALL
	local reserved=';/?:@&=+$,'
	local mark='_.!~*''()-'
	local dont_escape="[A-Za-z0-9"
	if [[ -z $opts[(r)-r] ]]; then
	 dont_escape+=$reserved
	fi
	# $mark must be last because of the "-"
	if [[ -z $opts[(r)-m] ]]; then
	 dont_escape+=$mark
	fi
	dont_escape+="]"

	# Implemented to use a single printf call and avoid subshells in the loop,
	# for performance
	local url_str=""
	for (( i = 1; i <= ${#str}; ++i )); do
	 byte="$str[i]"
	 if [[ "$byte" =~ "$dont_escape" ]]; then
		 url_str+="$byte"
	 else
		 if [[ "$byte" == " " && -n $spaces_as_plus ]]; then
			 url_str+="+"
		 else
			 ord=$(( [##16] #byte ))
			 url_str+="%$ord"
		 fi
	 fi
	done
	echo -E "$url_str"
}

# Runs before showing the prompt
function mzc_termsupport_precmd {
	[[ "${DISABLE_AUTO_TITLE:-}" == true ]] && return
	title $ZSH_THEME_TERM_TAB_TITLE_IDLE $ZSH_THEME_TERM_TITLE_IDLE
}

# Runs before executing the command
function mzc_termsupport_preexec {
	[[ "${DISABLE_AUTO_TITLE:-}" == true ]] && return

	emulate -L zsh

	# split command into array of arguments
	local -a cmdargs
	cmdargs=("${(z)2}")
	# if running fg, extract the command from the job description
	if [[ "${cmdargs[1]}" = fg ]]; then
	 # get the job id from the first argument passed to the fg command
	 local job_id jobspec="${cmdargs[2]#%}"
	 # logic based on jobs arguments:
	 # http://zsh.sourceforge.net/Doc/Release/Jobs-_0026-Signals.html#Jobs
	 # https://www.zsh.org/mla/users/2007/msg00704.html
	 case "$jobspec" in
		 <->) # %number argument:
			 # use the same <number> passed as an argument
			 job_id=${jobspec} ;;
		 ""|%|+) # empty, %% or %+ argument:
			 # use the current job, which appears with a + in $jobstates:
			 # suspended:+:5071=suspended (tty output)
			 job_id=${(k)jobstates[(r)*:+:*]} ;;
		 -) # %- argument:
			 # use the previous job, which appears with a - in $jobstates:
			 # suspended:-:6493=suspended (signal)
			 job_id=${(k)jobstates[(r)*:-:*]} ;;
		 [?]*) # %?string argument:
			 # use $jobtexts to match for a job whose command *contains* <string>
			 job_id=${(k)jobtexts[(r)*${(Q)jobspec}*]} ;;
		 *) # %string argument:
			 # use $jobtexts to match for a job whose command *starts with* <string>
			 job_id=${(k)jobtexts[(r)${(Q)jobspec}*]} ;;
	 esac

	 # override preexec function arguments with job command
	 if [[ -n "${jobtexts[$job_id]}" ]]; then
		 1="${jobtexts[$job_id]}"
		 2="${jobtexts[$job_id]}"
	 fi
	fi

	# cmd name only, or if this is sudo or ssh, the next cmd
	local CMD=${1[(wr)^(*=*|sudo|ssh|mosh|rake|-*)]:gs/%/%%}
	local LINE="${2:gs/%/%%}"

	title '$CMD' '%100>...>$LINE%<<'
}

# Emits the control sequence to notify many terminal emulators
# of the cwd
#
# Identifies the directory using a file: URI scheme, including
# the host name to disambiguate local vs. remote paths.
function mzc_termsupport_cwd {
	# Percent-encode the host and path names.
	local URL_HOST URL_PATH
	URL_HOST="$(zsh_urlencode -P $HOST)" || return 1
	URL_PATH="$(zsh_urlencode -P $PWD)" || return 1

	# common control sequence (OSC 7) to set current host and path
	printf "\e]7;%s\a" "file://${URL_HOST}${URL_PATH}"
}