├── .gitignore
├── LICENSE
├── README.md
├── completions
└── mm.fish
├── docs
├── logo.png
└── mm.gif
└── functions
├── __mm_dependencies.fish
└── mm.fish
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .DS_Store
3 | playground.fish
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Esse Woods
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | [](https://github.com/OakNinja/MakeMeFish/raw/master/docs/mm.gif)
4 |
5 | MakeMeFish simplifies the usage of Makefiles by providing quick navigation and searching through make targets.
6 |
7 | ## Features
8 |
9 | - **Type ahead searching** - just write a few characters to filter out the targets you are looking for
10 | - **Preview** - When selecting a target, an excerpt of the target will be shown in the makefile, with match highlighting
11 | - **Snappy** - fzf-ingly fast!
12 |
13 | ## Prerequisities
14 |
15 | - Fish shell 3+
16 | - fzf https://github.com/junegunn/fzf#installation
17 |
18 | Don't use fish? Get in touch if you want MakeMe support in your shell.
19 |
20 | ## Install using omf
21 |
22 | `omf install makeme`
23 |
24 | ## Install using fisher
25 |
26 | `fisher install oakninja/MakeMeFish`
27 |
28 | or
29 |
30 | `fisher install oakninja/MakeMeFish@next-release`
31 |
32 | to get the latest version.
33 |
34 | it's also possible to get the previous version by running
35 |
36 | `fisher install oakninja/MakeMeFish@previous-version`
37 |
38 | ## Install manually
39 |
40 | Download and copy `mm.fish` to `~/.config/fish/functions`
41 |
42 | or run
43 |
44 | `curl https://raw.githubusercontent.com/OakNinja/MakeMeFish/master/mm.fish?nocache --create-dirs -sLo ~/.config/fish/functions/mm.fish`
45 |
46 | ## Usage
47 |
48 | _Basic usage:_
49 | type `mm`, if there is a Makefile in the current working directory, all targets will be listed. Start typing to filter targets.
50 |
51 | _Parameters:_
52 |
53 | - `-h` or `--help` to print the help.
54 | - `-f ` to specify a makefile if you have several in the cwd, or if you have a non-standard name.
55 | - `-i` to start MakeMefish in interactive mode. In interactive mode, the selected target will be executed and you will then be returned to the selection prompt. Please note that executed commands won't be added to your command history.
56 | - `` eg. add an arbitrary keyword to start MakeMeFish with a pre-populated query (editable at runtime)
57 |
58 | ## Examples
59 |
60 | `mm build` will start `MakeMeFish` with an initial query which will filter for targets containing the substring `build`.
61 | Similarly, `mm foo bar` will filter on targets containing both `foo` and `bar`
62 |
63 | ---
64 |
65 | `mm -f MyFancyMakeFile` will start `MakeMeFish` and parse the file `MyFancyMakeFile` instead of trying to find a makefile with a GNU make standard name.
66 |
67 | ---
68 |
69 | `mm -i` will run `MakeMeFish` in interactive mode
70 |
71 | ---
72 |
73 | _All flags and parameters can be combined, and added in any order, eg._
74 |
75 | `mm foo -i -f MyFancyMakeFile` is equivalent to `mm -f MyFancyMakeFile foo -i`
76 |
--------------------------------------------------------------------------------
/completions/mm.fish:
--------------------------------------------------------------------------------
1 | complete -c mm -s f -r --description 'Usage: mm -f '
2 | complete -c mm -s i -f --description 'Interactive mode'
3 | complete -c mm -s h -l help -f --description 'Display help'
4 | # complete -c mm -l install -f --description 'Install guide' Not implemented yet
--------------------------------------------------------------------------------
/docs/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OakNinja/MakeMeFish/7ea594574572a7fa2253d679a43ec57fa80aa440/docs/logo.png
--------------------------------------------------------------------------------
/docs/mm.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OakNinja/MakeMeFish/7ea594574572a7fa2253d679a43ec57fa80aa440/docs/mm.gif
--------------------------------------------------------------------------------
/functions/__mm_dependencies.fish:
--------------------------------------------------------------------------------
1 | function __mm_confirm --description 'Confirm' --argument prompt
2 | if test -z "$prompt"
3 | set prompt "Continue?"
4 | end
5 |
6 | while true
7 | read -p 'echo -ne "$prompt ["; set_color green; echo -ne "y"; set_color normal; echo -ne "/"; set_color red; echo -ne "N"; set_color normal; echo -ne "]: "; ' -l confirm
8 |
9 | switch $confirm
10 | case Y y
11 | return 0
12 | case '' N n
13 | return 1
14 | end
15 | end
16 | end
17 |
18 | function __mm_echo --argument color --argument text --argument no_newline
19 | set_color $color;
20 | if test -n "$no_newline"
21 | echo -ne $text
22 | else
23 | echo $text
24 | end
25 | set_color normal;
26 | end
27 |
28 | function __mm_check_dependencies
29 | if type -q "fzf"
30 | return 0
31 | else
32 | return 1
33 | end
34 | end
35 |
36 |
37 | function __mm_install_dependencies
38 | if __mm_check_dependencies
39 | echo ""
40 | __mm_echo green "Dependencies already installed"
41 | echo ""
42 | return 0
43 | else
44 | echo ""
45 | echo "MakeMeFish is dependent of fzf - the command line fuzzy finder."
46 | if __mm_confirm "fzf is not installed. Would you like to install fzf?"
47 | switch (uname)
48 | case Linux Darwin
49 | if type -q "brew"
50 | if __mm_confirm "You are using brew - would you like to install fzf through brew?"
51 | echo (brew install fzf)
52 | return 0
53 | end
54 | end
55 | case FreeBSD NetBSD DragonFly
56 | echo (pkg install fzf)
57 | return 0
58 | case '*'
59 | echo "Unknown OS"
60 | end
61 | __mm_echo red "Could not install automatically."
62 | end
63 | echo -ne "Go to "; __mm_echo blue "https://github.com/junegunn/fzf#installation" 1; echo -ne " and follow the instructions for your environment."
64 | return 1
65 | end
66 | end
67 |
68 | function __mm_dependencies
69 | if __mm_check_dependencies
70 | return 0
71 | else
72 | if __mm_install_dependencies true
73 | return 0
74 | else
75 | return 1
76 | end
77 | end
78 | end
--------------------------------------------------------------------------------
/functions/mm.fish:
--------------------------------------------------------------------------------
1 | function mm --description "MakeMeFish - List all Make targets in the Makefile of the current directory"
2 |
3 | set current_pos 1
4 | while test (count $argv) -ge $current_pos
5 | # Check if a help flag was passed to mm
6 | set help_flags -- -h --help
7 | if contains -- $argv[$current_pos] $help_flags
8 | echo ""
9 | echo " Usage:"
10 | 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."
11 | echo " " "To filter for a specific target, just start typing and targets will be filtered as you type."
12 | echo " " (set_color green)"mm "(set_color normal) "will start MakeMeFish with an initial, editable query" (set_color green)""(set_color normal)
13 | 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."
14 | echo " " (set_color green)"mm -f "(set_color normal) "to specify what Makefile to load."
15 | echo " " "All flags can be combined in any order."
16 | echo ""
17 | return 0
18 | else if test $argv[$current_pos] = "-f"
19 | set current_pos (math "$current_pos+1") # skip the next
20 | set filename $argv[$current_pos]
21 | else if test $argv[$current_pos] = "-i"
22 | set interactive 1
23 | else
24 | if set -q initial_query
25 | set initial_query $initial_query $argv[$current_pos]
26 | else
27 | set initial_query $argv[$current_pos]
28 | end
29 | end
30 | set current_pos (math "$current_pos+1")
31 | end
32 |
33 | function __mm_get_makefile_name -a 'filename'
34 | if test -n "$filename"
35 | set makefile_filenames $filename
36 | else
37 | set makefile_filenames 'GNUmakefile' 'makefile' 'Makefile'
38 | end
39 | for filename in $makefile_filenames
40 | if test -f $filename
41 | echo $filename
42 | break
43 | end
44 | end
45 | end
46 |
47 | # Based on:
48 | # https://github.com/fish-shell/fish-shell/blob/8e418f5205106b11f83fa1956076a9b20c56f0f9/share/completions/make.fish
49 | # and
50 | # https://stackoverflow.com/a/26339924
51 | function __mm_parse_makefile -a 'filename'
52 | # Ensure correct locale set
53 | set -lx LC_ALL C
54 |
55 | set makeflags -f $filename
56 |
57 | # first awk merges any line that ends with a backslash with the next line
58 | if make --version 2>/dev/null | string match -q 'GNU*'
59 | make $makeflags -pRrq : 2>/dev/null |
60 | awk '{if (sub(/\\\$/,"")) printf "%s", $0; else print $0}' |
61 | awk -F: '/^# Files/,/^# Finished Make data base/ {
62 | if ($1 == "# Not a target") skip = 1;
63 | if ($1 !~ "^[#.\t]") {
64 | if (!skip) print $1; skip=0
65 | }
66 | }' 2>/dev/null
67 | else
68 | # BSD make
69 | make $makeflags -d g1 -rn >/dev/null 2>| awk -F, '/^#\*\*\* Input graph:/,/^$/ {if ($1 !~ "^#... ") {gsub(/# /,"",$1); print $1}}' 2>/dev/null
70 | end
71 | end
72 |
73 | function __mm_get_targets -a 'filename'
74 | set static_targets
75 | set file_targets
76 | set generated_targets
77 |
78 | set parsed_makefile (__mm_parse_makefile $filename | sort -f)
79 | for row in $parsed_makefile # Loop over all rows in the Makefile
80 | set row (string trim $row)
81 | if test -n "$row" # No blanks plz
82 | if test (string match -r '.\.|\/' $row) # this is a file or path
83 | set file_targets $file_targets $row
84 | else # grep the target and see if it's generated by a function or a true target
85 | set found_in_file (grep "$row:" $filename)
86 | if test -n "$found_in_file"
87 | set static_targets $static_targets $row # true target
88 | else
89 | set generated_targets $generated_targets $row # generated by function
90 | end
91 | end
92 | end
93 | end
94 |
95 | string split " " $static_targets $file_targets $generated_targets
96 | end
97 |
98 | function __mm_fzf_command -a 'filename' -a 'interactive' -a 'make_command' -a 'query'
99 | if [ $interactive -eq 1 ]
100 | set fzf_interactive "--bind \"enter:execute:$make_command {}; echo; echo 'Done'; sleep 1\""
101 | end
102 |
103 | if test -n "$query"
104 | set fzf_query "--query=$query"
105 | end
106 | set fzf_opts "--read0
107 | $fzf_query
108 | $fzf_interactive
109 | --height 60%
110 | --layout=reverse
111 | --border
112 | --preview-window='right:60%'
113 | --preview='grep
114 | --color=always -A 10 -B 1 \^{}: $filename; or echo -GENERATED TARGET-'"
115 |
116 | set -q FZF_TMUX; or set FZF_TMUX 0
117 | set -q FZF_TMUX_HEIGHT; or set FZF_TMUX_HEIGHT 60%
118 | if [ $FZF_TMUX -eq 1 ]
119 | echo "fzf-tmux -d$FZF_TMUX_HEIGHT $fzf_opts"
120 | else
121 | echo "fzf $fzf_opts"
122 | end
123 | end
124 |
125 | if __mm_dependencies
126 | set custom_filename $filename
127 | set filename (__mm_get_makefile_name $filename)
128 | if test -z "$filename"
129 | echo 'No makefile found in the current working directory'
130 | else
131 | set targets (__mm_get_targets $filename)
132 | if test -n "$targets"
133 | if test -n "$custom_filename"
134 | set make_command "make -f $filename"
135 | else
136 | set make_command "make"
137 | end
138 | # Interactive?
139 | if test -n "$interactive"; and test $interactive -eq 1
140 | string join0 -- $targets | eval (__mm_fzf_command $filename 1 $make_command $initial_query)
141 | else
142 | 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
143 | set result (string trim -- $result) # Trim newlines and whitespace from the command
144 | and commandline -- "$make_command $result" # Prepend the make command
145 | commandline -f repaint # Repaint command line
146 | end
147 | else
148 | echo "No targets found in $filename"
149 | end
150 | end
151 | end
152 |
153 | end
--------------------------------------------------------------------------------