mirror of
https://github.com/platformio/platformio-core.git
synced 2025-07-31 18:44:27 +02:00
Improved tab completion support for Bash, ZSH, and Fish shells // Resolve #4114
This commit is contained in:
@@ -12,6 +12,7 @@ PlatformIO Core 5
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- Added support for a new ``headers`` field in `library.json <https://docs.platformio.org/en/latest/librarymanager/config.html>`__ (declare a list of header files that can be included in a project source files using ``#include <...>`` directive)
|
||||
- Improved tab completion support for Bash, ZSH, and Fish shells (`issue #4114 <https://github.com/platformio/platformio-core/issues/4114>`_)
|
||||
- Improved support for projects located on a network share (`issue #3417 <https://github.com/platformio/platformio-core/issues/3417>`_, `issue #3926 <https://github.com/platformio/platformio-core/issues/3926>`_, `issue #4099 <https://github.com/platformio/platformio-core/issues/4099>`_)
|
||||
- Upgraded build engine to the SCons 4.3 (`release notes <https://github.com/SCons/scons/blob/rel_4.3.0/CHANGES.txt>`__)
|
||||
- Fixed an issue with the CLion project generator when a macro contains a space (`issue #4102 <https://github.com/platformio/platformio-core/issues/4102>`_)
|
||||
|
2
docs
2
docs
Submodule docs updated: ad3f9b62cf...b6322c062f
@@ -24,13 +24,6 @@ from platformio import __version__, exception
|
||||
from platformio.commands import PlatformioCLI
|
||||
from platformio.compat import IS_CYGWIN, ensure_python3
|
||||
|
||||
try:
|
||||
import click_completion # pylint: disable=import-error
|
||||
|
||||
click_completion.init()
|
||||
except: # pylint: disable=bare-except
|
||||
pass
|
||||
|
||||
|
||||
@click.command(
|
||||
cls=PlatformioCLI, context_settings=dict(help_option_names=["-h", "--help"])
|
||||
|
@@ -14,7 +14,6 @@
|
||||
|
||||
import json
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import click
|
||||
@@ -22,6 +21,7 @@ from tabulate import tabulate
|
||||
|
||||
from platformio import __version__, compat, fs, proc, util
|
||||
from platformio.commands.system.completion import (
|
||||
ShellType,
|
||||
get_completion_install_path,
|
||||
install_completion_code,
|
||||
uninstall_completion_code,
|
||||
@@ -150,23 +150,11 @@ def system_prune(force, dry_run, cache, core_packages, platform_packages):
|
||||
|
||||
@cli.group("completion", short_help="Shell completion support")
|
||||
def completion():
|
||||
# pylint: disable=import-error,import-outside-toplevel
|
||||
try:
|
||||
import click_completion # pylint: disable=unused-import,unused-variable
|
||||
except ImportError:
|
||||
click.echo("Installing dependent packages...")
|
||||
subprocess.check_call(
|
||||
[proc.get_pythonexe_path(), "-m", "pip", "install", "click-completion"],
|
||||
)
|
||||
pass
|
||||
|
||||
|
||||
@completion.command("install", short_help="Install shell completion files/code")
|
||||
@click.option(
|
||||
"--shell",
|
||||
default=None,
|
||||
type=click.Choice(["fish", "bash", "zsh", "powershell", "auto"]),
|
||||
help="The shell type, default=auto",
|
||||
)
|
||||
@click.argument("shell", type=click.Choice([t.value for t in ShellType]))
|
||||
@click.option(
|
||||
"--path",
|
||||
type=click.Path(file_okay=True, dir_okay=False, readable=True, resolve_path=True),
|
||||
@@ -174,26 +162,18 @@ def completion():
|
||||
"The standard installation path is used by default.",
|
||||
)
|
||||
def completion_install(shell, path):
|
||||
|
||||
import click_completion # pylint: disable=import-outside-toplevel,import-error
|
||||
|
||||
shell = shell or click_completion.get_auto_shell()
|
||||
shell = ShellType(shell)
|
||||
path = path or get_completion_install_path(shell)
|
||||
install_completion_code(shell, path)
|
||||
click.echo(
|
||||
"PlatformIO CLI completion has been installed for %s shell to %s \n"
|
||||
"Please restart a current shell session."
|
||||
% (click.style(shell, fg="cyan"), click.style(path, fg="blue"))
|
||||
% (click.style(shell.name, fg="cyan"), click.style(path, fg="blue"))
|
||||
)
|
||||
|
||||
|
||||
@completion.command("uninstall", short_help="Uninstall shell completion files/code")
|
||||
@click.option(
|
||||
"--shell",
|
||||
default=None,
|
||||
type=click.Choice(["fish", "bash", "zsh", "powershell", "auto"]),
|
||||
help="The shell type, default=auto",
|
||||
)
|
||||
@click.argument("shell", type=click.Choice([t.value for t in ShellType]))
|
||||
@click.option(
|
||||
"--path",
|
||||
type=click.Path(file_okay=True, dir_okay=False, readable=True, resolve_path=True),
|
||||
@@ -201,14 +181,11 @@ def completion_install(shell, path):
|
||||
"The standard installation path is used by default.",
|
||||
)
|
||||
def completion_uninstall(shell, path):
|
||||
|
||||
import click_completion # pylint: disable=import-outside-toplevel,import-error
|
||||
|
||||
shell = shell or click_completion.get_auto_shell()
|
||||
shell = ShellType(shell)
|
||||
path = path or get_completion_install_path(shell)
|
||||
uninstall_completion_code(shell, path)
|
||||
click.echo(
|
||||
"PlatformIO CLI completion has been uninstalled for %s shell from %s \n"
|
||||
"Please restart a current shell session."
|
||||
% (click.style(shell, fg="cyan"), click.style(path, fg="blue"))
|
||||
% (click.style(shell.name, fg="cyan"), click.style(path, fg="blue"))
|
||||
)
|
||||
|
@@ -13,61 +13,75 @@
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
from enum import Enum
|
||||
|
||||
import click
|
||||
|
||||
from platformio.compat import IS_MACOS
|
||||
|
||||
|
||||
class ShellType(Enum):
|
||||
FISH = "fish"
|
||||
ZSH = "zsh"
|
||||
BASH = "bash"
|
||||
|
||||
|
||||
def get_completion_install_path(shell):
|
||||
home_dir = os.path.expanduser("~")
|
||||
prog_name = click.get_current_context().find_root().info_name
|
||||
if shell == "fish":
|
||||
if shell == ShellType.FISH:
|
||||
return os.path.join(
|
||||
home_dir, ".config", "fish", "completions", "%s.fish" % prog_name
|
||||
)
|
||||
if shell == "bash":
|
||||
return os.path.join(home_dir, ".bash_completion")
|
||||
if shell == "zsh":
|
||||
if shell == ShellType.ZSH:
|
||||
return os.path.join(home_dir, ".zshrc")
|
||||
if shell == "powershell":
|
||||
return subprocess.check_output(
|
||||
["powershell", "-NoProfile", "echo $profile"]
|
||||
).strip()
|
||||
if shell == ShellType.BASH:
|
||||
return os.path.join(home_dir, ".bash_completion")
|
||||
raise click.ClickException("%s is not supported." % shell)
|
||||
|
||||
|
||||
def get_completion_code(shell):
|
||||
if shell == ShellType.FISH:
|
||||
return "eval (env _PIO_COMPLETE=fish_source pio)"
|
||||
if shell == ShellType.ZSH:
|
||||
code = "autoload -Uz compinit\ncompinit\n" if IS_MACOS else ""
|
||||
return code + 'eval "$(_PIO_COMPLETE=zsh_source pio)"'
|
||||
if shell == ShellType.BASH:
|
||||
return 'eval "$(_PIO_COMPLETE=bash_source pio)"'
|
||||
raise click.ClickException("%s is not supported." % shell)
|
||||
|
||||
|
||||
def is_completion_code_installed(shell, path):
|
||||
if shell == "fish" or not os.path.exists(path):
|
||||
if shell == ShellType.FISH or not os.path.exists(path):
|
||||
return False
|
||||
|
||||
import click_completion # pylint: disable=import-error,import-outside-toplevel
|
||||
|
||||
with open(path, encoding="utf8") as fp:
|
||||
return click_completion.get_code(shell=shell) in fp.read()
|
||||
return get_completion_code(shell) in fp.read()
|
||||
|
||||
|
||||
def install_completion_code(shell, path):
|
||||
import click_completion # pylint: disable=import-error,import-outside-toplevel
|
||||
|
||||
if is_completion_code_installed(shell, path):
|
||||
return None
|
||||
|
||||
return click_completion.install(shell=shell, path=path, append=shell != "fish")
|
||||
append = shell != ShellType.FISH
|
||||
with open(path, mode="a" if append else "w", encoding="utf8") as fp:
|
||||
if append:
|
||||
fp.write("\n\n# Begin: PlatformIO Core completion support\n")
|
||||
fp.write(get_completion_code(shell))
|
||||
if append:
|
||||
fp.write("\n# End: PlatformIO Core completion support\n\n")
|
||||
return True
|
||||
|
||||
|
||||
def uninstall_completion_code(shell, path):
|
||||
if not os.path.exists(path):
|
||||
return True
|
||||
if shell == "fish":
|
||||
if shell == ShellType.FISH:
|
||||
os.remove(path)
|
||||
return True
|
||||
|
||||
import click_completion # pylint: disable=import-error,import-outside-toplevel
|
||||
|
||||
with open(path, "r+", encoding="utf8") as fp:
|
||||
contents = fp.read()
|
||||
fp.seek(0)
|
||||
fp.truncate()
|
||||
fp.write(contents.replace(click_completion.get_code(shell=shell), ""))
|
||||
fp.write(contents.replace(get_completion_code(shell), ""))
|
||||
|
||||
return True
|
||||
|
Reference in New Issue
Block a user