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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
|
function mm --description "MakeMeFish - List all Make targets in the Makefile of the current directory"
set current_pos 1
while test (count $argv) -ge $current_pos
# Check if a help flag was passed to mm
set help_flags -- -h --help
if contains -- $argv[$current_pos] $help_flags
echo ""
echo " Usage:"
echo " " (set_color green)"mm"(set_color normal) "will look for a Makefile in the order specified by GNU Make and list all targets in it."
echo " " "To filter for a specific target, just start typing and targets will be filtered as you type."
echo " " (set_color green)"mm <keyword>"(set_color normal) "will start MakeMeFish with an initial, editable query" (set_color green)"<keyword>"(set_color normal)
echo " " (set_color green)"mm -i"(set_color normal) "will start MakeMeFish in interactive mode. When a target is run, you will return to the selection menu."
echo " " (set_color green)"mm -f <filename>"(set_color normal) "to specify what Makefile to load."
echo " " "All flags can be combined in any order."
echo ""
return 0
else if test $argv[$current_pos] = "-f"
set current_pos (math "$current_pos+1") # skip the next
set filename $argv[$current_pos]
else if test $argv[$current_pos] = "-i"
set interactive 1
else
if set -q initial_query
set initial_query $initial_query $argv[$current_pos]
else
set initial_query $argv[$current_pos]
end
end
set current_pos (math "$current_pos+1")
end
function __mm_get_makefile_name -a 'filename'
if test -n "$filename"
set makefile_filenames $filename
else
set makefile_filenames 'GNUmakefile' 'makefile' 'Makefile'
end
for filename in $makefile_filenames
if test -f $filename
echo $filename
break
end
end
end
# Based on:
# https://github.com/fish-shell/fish-shell/blob/8e418f5205106b11f83fa1956076a9b20c56f0f9/share/completions/make.fish
# and
# https://stackoverflow.com/a/26339924
function __mm_parse_makefile -a 'filename'
# Ensure correct locale set
set -lx LC_ALL C
set makeflags -f $filename
# first awk merges any line that ends with a backslash with the next line
if make --version 2>/dev/null | string match -q 'GNU*'
make $makeflags -pRrq : 2>/dev/null |
awk '{if (sub(/\\\$/,"")) printf "%s", $0; else print $0}' |
awk -F: '/^# Files/,/^# Finished Make data base/ {
if ($1 == "# Not a target") skip = 1;
if ($1 !~ "^[#.\t]") {
if (!skip) print $1; skip=0
}
}' 2>/dev/null
else
# BSD make
make $makeflags -d g1 -rn >/dev/null 2>| awk -F, '/^#\*\*\* Input graph:/,/^$/ {if ($1 !~ "^#... ") {gsub(/# /,"",$1); print $1}}' 2>/dev/null
end
end
function __mm_get_targets -a 'filename'
set static_targets
set file_targets
set generated_targets
set parsed_makefile (__mm_parse_makefile $filename | sort -f)
for row in $parsed_makefile # Loop over all rows in the Makefile
set row (string trim $row)
if test -n "$row" # No blanks plz
if test (string match -r '.\.|\/' $row) # this is a file or path
set file_targets $file_targets $row
else # grep the target and see if it's generated by a function or a true target
set found_in_file (grep "$row:" $filename)
if test -n "$found_in_file"
set static_targets $static_targets $row # true target
else
set generated_targets $generated_targets $row # generated by function
end
end
end
end
string split " " $static_targets $file_targets $generated_targets
end
function __mm_fzf_command -a 'filename' -a 'interactive' -a 'make_command' -a 'query'
if [ $interactive -eq 1 ]
set fzf_interactive "--bind \"enter:execute:$make_command {}; echo; echo 'Done'; sleep 1\""
end
if test -n "$query"
set fzf_query "--query=$query"
end
set fzf_opts "--read0
$fzf_query
$fzf_interactive
--height 60%
--layout=reverse
--border
--preview-window='right:60%'
--preview='grep
--color=always -A 10 -B 1 \^{}: $filename; or echo -GENERATED TARGET-'"
set -q FZF_TMUX; or set FZF_TMUX 0
set -q FZF_TMUX_HEIGHT; or set FZF_TMUX_HEIGHT 60%
if [ $FZF_TMUX -eq 1 ]
echo "fzf-tmux -d$FZF_TMUX_HEIGHT $fzf_opts"
else
echo "fzf $fzf_opts"
end
end
if __mm_dependencies
set custom_filename $filename
set filename (__mm_get_makefile_name $filename)
if test -z "$filename"
echo 'No makefile found in the current working directory'
else
set targets (__mm_get_targets $filename)
if test -n "$targets"
if test -n "$custom_filename"
set make_command "make -f $filename"
else
set make_command "make"
end
# Interactive?
if test -n "$interactive"; and test $interactive -eq 1
string join0 -- $targets | eval (__mm_fzf_command $filename 1 $make_command $initial_query)
else
string join0 -- $targets | eval (__mm_fzf_command $filename 0 $make_command $initial_query) | read -lz result # print targets as a list, pipe them to fzf, put the chosen command in $result
set result (string trim -- $result) # Trim newlines and whitespace from the command
and commandline -- "$make_command $result" # Prepend the make command
commandline -f repaint # Repaint command line
end
else
echo "No targets found in $filename"
end
end
end
end
|