Skip to content

[WIP] Implemented custom auto-completion for Makefiles [Feedback wanted] #491

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from

Conversation

TobiasFaller
Copy link

@TobiasFaller TobiasFaller commented Jan 14, 2021

This pull request introduces the ability to have a custom Makefile target that generates auto-completion input for the bash shell.
With this feature it is possible to customize the completion list that is displayed in the shell.

The Makefile target returns a space and newline separated list of custom completion options.
Since the Makefile has full control over the returned list it can add custom build targets which are not directly specified as a Makefile target.
Because this might have some security implications - executing the Makefile target on auto-completion - the feature is disabled by default.

Configuration options:

  • BASH_COMPLETION_MAKE_ENABLE_MAKEFILE_TARGET: Enables the feature (Default is "0")
  • BASH_COMPLETION_MAKE_MAKEFILE_TARGET: Specifies Makefile target to execute (Default is ".BASH-COMPLETION")

Example Makefile which implements a static list:

.PHONY: .BASH-COMPLETION

.BASH-COMPLETION:
	@echo 'build/debug/AppA build/debug/AppB'
	@echo 'build/release/AppA build/release/AppB'

build/debug/%: %Main.c
	echo "Building $(@F) (Debug)"
	gcc -O1 -g -o $(@F) $^

build/release/%: %Main.c
	echo "Building $(@F) (Release)"
	gcc -O3 -o $(@F) $^

Example Makefile which implements an auto-generated list which is fed by bazel:

.PHONY: .BASH-COMPLETION

.BASH-COMPLETION:
	@$(eval $@_BAZEL_TARGETS := $(shell $(BAZEL) query 'kind(rule, //src:*)' 2>/dev/null))
	@$(eval $@_BAZEL_TESTS := $(shell $(BAZEL) query 'kind(rule, //test:*)' 2>/dev/null))
	@echo 'build/debug/* build/release/*'
	@echo 'test/debug/* test/release/*'
	@echo '$(subst //src:,build/debug/,$($@_BAZEL_TARGETS))'
	@echo '$(subst //src:,build/release/,$($@_BAZEL_TARGETS))'
	@echo '$(subst //test:,test/debug/,$($@_BAZEL_TESTS))'
	@echo '$(subst //test:,test/release/,$($@_BAZEL_TESTS))'

build/debug/%:
	echo "Building $(@F) (Debug)"
	bazel build --config=debug //src:$(@F)

build/release/%:
	echo "Building $(@F) (Release)"
	bazel build --config=release //src:$(@F)

test/debug/%:
	echo "Testing $(@F) (Debug)"
	bazel test --config=debug //test:$(@F)

test/release/%:
	echo "Testing $(@F) (Release)"
	bazel test --config=release //test:$(@F)

TODO:

  • Add unit tests

Getting feedback if this feature makes sense and about the implementation would be nice.

@TobiasFaller TobiasFaller force-pushed the master branch 7 times, most recently from 19fad7e to b431da0 Compare January 14, 2021 23:59
@TobiasFaller TobiasFaller changed the title [WIP] Implemented custom auto-completion for Makefiles [WIP] Implemented custom auto-completion for Makefiles [Feedback wanted] Jan 17, 2021
@scop scop force-pushed the master branch 3 times, most recently from c0e9459 to 09307f8 Compare March 30, 2021 15:12
@akinomyoga
Copy link
Collaborator

I have a question about this new feature. Have this special target .BASH-COMPLETION: and customized make completion used in any popular projects? I searched in GitHub but I couldn't find any:

If this has never been used in popular projects and there is no future plan to be adopted in popular projects, I'm not sure if .BASH-COMPLETION: will be defined by other developers and then will be used by other users. In particular, as this feature isn't turned on by default for the security reason that you mentioned and only works if there is .BASH-COMPLETION: target in Makefile, I suspect no one notices this feature, and this feature will never be used by other people.

At least, we need to promote it if you want it used by other people. If you are going to promote this one, I think it is more effective to create a separate small repository so that users can readily try it out by just copying it in their configuration folder rather than cloning the entire bash_completion of the latest version. But I cannot ensure that it will finally be popular.

@TobiasFaller
Copy link
Author

Hello @akinomyoga, tank you for the valuable feedback. As you proposed I will upload the patches to a separate repository and see if somebody is interested in this feature.

@akinomyoga
Copy link
Collaborator

Thank you! If you create a repository, gist, or whatever, you may add a link to your completion script in the recently-created wiki page of external completion scripts.

@TobiasFaller
Copy link
Author

TobiasFaller commented Jul 19, 2021

@akinomyoga Thank you, the patch is now independently available under the following link: TobiasFaller/custom-makefile-completion. Could you please add it to the list of external completions in the Wiki?

@akinomyoga
Copy link
Collaborator

Thank you for the information! I have added the entry in the list.

From README, TobiasFaller/custom-makefile-completion

How to install

Run the following command inside your bash-completion installation folder to apply the custom extension.

Letting users apply patches is a valid way to provide custom completion, but usually we provide users with the customization method through user's custom completion directory (~/.local/share/bash-completion/completions or more correctly, ${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions).

  • In most cases, users will use bash-completion through the distribution package in /usr/share/bash-completion, etc. However, it is generally not recommended to directly modify the package contents. To use the patch, the user instead needs to manually download bash-completion in another place and then directly apply the patch to that bash-completion. It's not impossible but not so convenient.
  • Instead, I think you may additionally provide a patched completion file (not diff) so that the user can just copy the completion file into ~/.local/share/bash-completion/completions/. In this case, the installation procedure would be something like
$ mkdir -p ~/.local/share/bash-completion/completions
$ wget https://raw.githubusercontent.com/TobiasFaller/custom-makefile-completion/main/custom-makefile-completion.bash
$ mv custom-makefile-completion.bash ~/.local/share/bash-completion/completions/make

Or, with more robust script,

#!/usr/bin/env bash

user_completion_dir=${BASH_COMPLETION_USER_DIR:-${XDG_DATA_HOME:-$HOME/.local/share}/bash-completion}/completions
url=https://raw.githubusercontent.com/TobiasFaller/custom-makefile-completion/main/custom-makefile-completion.bash
mkdir -p "$user_completion_dir"
wget "$url" -O "$user_completion_dir"/make

Make sure to set BASH_COMPLETION_MAKE_ENABLE_MAKEFILE_TARGET to 1 in your global .bashrc or .bash_profile configuration to enable / test the feature.

  • We don't basically recommend providing options for the behavior of each completion, but if it is needed we usually use the variable name of the form COMP_${CommandName}_${OptionName}. In this case, it would be something like COMP_MAKE_ENABLE_MAKEFILE_TARGET. You can also check the related ongoing discussion Customizability and naming conventions for each completion #539.
  • The name MAKEFILE_TARGET seems too general. Something more specific such as CUSTOM_TARGET might be better.

How to use

Below is an example Makefile which implements a static list that will be listed if this bash complection is enabled.

The usage examples are nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants