mirror of
https://github.com/HorlogeSkynet/SSHubl.git
synced 2025-05-01 16:00:17 +02:00
Disables spellcheck in remote terminal view (Terminus v0.3.32+)
This patch replaces previous Terminus package detection by a proper `terminus_open` lookup (actually `TerminusOpenCommand` command class). SSHubl won't (try to) consume PackageControl API anymore, which should result in better performance when opening a remote terminal for the first time. New `st_utils.get_command_class` function comes with some proper testing (including its conditional cache feature). As Terminus v0.3.32 was released on 15/08/2024, we expect it to be globally rolled out before next version of SSHubl.
This commit is contained in:
parent
3ea6f40cfb
commit
d3ef40fe79
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Disable spellcheck in remote terminal view (Terminus v0.3.32+)
|
||||
|
||||
## [0.4.0] - 2024-08-07
|
||||
|
||||
### Added
|
||||
|
@ -26,9 +26,5 @@ ignore_missing_imports = true
|
||||
module = "sublime_plugin.*"
|
||||
ignore_missing_imports = true
|
||||
|
||||
[[tool.mypy.overrides]]
|
||||
module = "package_control.*"
|
||||
ignore_missing_imports = true
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
|
@ -24,7 +24,7 @@ from .ssh_utils import (
|
||||
from .st_utils import (
|
||||
format_ip_addr,
|
||||
get_absolute_purepath_flavour,
|
||||
is_package_installed,
|
||||
get_command_class,
|
||||
parse_ssh_connection,
|
||||
validate_forward_target,
|
||||
)
|
||||
@ -708,10 +708,11 @@ class SshCloseDirCommand(sublime_plugin.TextCommand):
|
||||
class SshTerminalCommand(sublime_plugin.TextCommand):
|
||||
@_with_session_identifier
|
||||
def run(self, _edit, identifier: str):
|
||||
# check Terminus third-party package is actually installed before continuing.
|
||||
# check for Terminus `terminus_open` command support before actually continuing.
|
||||
# we check for a (hidden) setting which allows package lookup bypass for developers who know
|
||||
# what they're doing
|
||||
if not _settings().get("terminus_is_installed") and not is_package_installed("Terminus"):
|
||||
terminus_open_command = get_command_class("TerminusOpenCommand")
|
||||
if not _settings().get("terminus_is_installed") and terminus_open_command is None:
|
||||
sublime.error_message("Please install Terminus package to open a remote terminal !")
|
||||
return
|
||||
|
||||
@ -721,18 +722,22 @@ class SshTerminalCommand(sublime_plugin.TextCommand):
|
||||
ssh_session = SshSession.get_from_project_data(session_identifier, window)
|
||||
title = str(ssh_session) if ssh_session is not None else None
|
||||
|
||||
window.run_command(
|
||||
"terminus_open",
|
||||
{
|
||||
"shell_cmd": shlex.join(
|
||||
get_base_ssh_cmd(
|
||||
session_identifier,
|
||||
("-q",),
|
||||
)
|
||||
),
|
||||
"title": title,
|
||||
},
|
||||
)
|
||||
terminus_open_args: typing.Dict[str, typing.Any] = {
|
||||
"shell_cmd": shlex.join(get_base_ssh_cmd(session_identifier, ("-q",))),
|
||||
"title": title,
|
||||
}
|
||||
|
||||
# Disable spellcheck in terminal view as it's usually irrelevant and report many misspelled
|
||||
# words on shells. Moreover, as we're connected to a different host it's even likely local
|
||||
# and remote locales do not match. Although, as it's an opinionated take, we also check for
|
||||
# a(nother) hidden setting before doing so :-)
|
||||
# Development note : `view_settings` argument is only supported by Terminus v0.3.32+
|
||||
if not _settings().get("honor_spell_check"):
|
||||
terminus_open_args["view_settings"] = {
|
||||
"spell_check": False,
|
||||
}
|
||||
|
||||
window.run_command("terminus_open", terminus_open_args)
|
||||
|
||||
def is_enabled(self):
|
||||
return bool(SshSession.get_identifiers_from_project_data(self.view.window()))
|
||||
|
@ -2,19 +2,12 @@ import contextlib
|
||||
import functools
|
||||
import getpass
|
||||
import ipaddress
|
||||
import itertools
|
||||
import re
|
||||
import typing
|
||||
from pathlib import Path, PurePath, PurePosixPath, PureWindowsPath
|
||||
from pathlib import PurePath, PurePosixPath, PureWindowsPath
|
||||
from urllib.parse import urlparse
|
||||
|
||||
import sublime
|
||||
|
||||
try:
|
||||
from package_control.package_manager import PackageManager
|
||||
except ModuleNotFoundError:
|
||||
PackageManager = None # pylint: disable=invalid-name
|
||||
|
||||
import sublime_plugin
|
||||
|
||||
# hostname regular expression (taken from <https://stackoverflow.com/a/106223>)
|
||||
HOSTNAME_REGEXP = re.compile(
|
||||
@ -49,26 +42,20 @@ def conditional_cache(no_cache_result: typing.Optional[tuple] = None):
|
||||
return decorator
|
||||
|
||||
|
||||
@conditional_cache(no_cache_result=(False,))
|
||||
def is_package_installed(package_name: str) -> bool:
|
||||
@conditional_cache(no_cache_result=(None,))
|
||||
def get_command_class(class_name: str) -> typing.Optional[typing.Type[sublime_plugin.Command]]:
|
||||
"""
|
||||
This function does its best to check whether a Sublime package is installed or not.
|
||||
It lists installed packages using Package Control API (if it's available), with fallback on
|
||||
brain-dead iterations through package folders (case-insensitively).
|
||||
This function does its best to check whether a command is known to Sublime.
|
||||
If it has been found, the command class is returned. `None` is returned otherwise.
|
||||
|
||||
Once a package has been found, result is cached to prevent unnecessary additional lookups.
|
||||
Once a command has been found, result is cached to prevent unnecessary additional lookups.
|
||||
At the moment, only Sublime "window commands" are processed.
|
||||
"""
|
||||
if PackageManager is not None:
|
||||
return package_name in PackageManager().list_packages()
|
||||
for command_class in sublime_plugin.window_command_classes:
|
||||
if command_class.__name__ == class_name:
|
||||
return command_class
|
||||
|
||||
for installed_package in itertools.chain(
|
||||
Path(sublime.installed_packages_path()).iterdir(),
|
||||
Path(sublime.packages_path()).iterdir(),
|
||||
):
|
||||
if package_name.casefold() == installed_package.stem.casefold():
|
||||
return True
|
||||
|
||||
return False
|
||||
return None
|
||||
|
||||
|
||||
@functools.lru_cache()
|
||||
|
@ -2,11 +2,15 @@
|
||||
|
||||
import unittest
|
||||
from pathlib import PurePosixPath, PureWindowsPath
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import sublime_plugin
|
||||
|
||||
from sshubl.commands import SshTerminalCommand
|
||||
from sshubl.st_utils import (
|
||||
format_ip_addr,
|
||||
get_absolute_purepath_flavour,
|
||||
get_command_class,
|
||||
parse_ssh_connection,
|
||||
pretty_forward_target,
|
||||
validate_forward_target,
|
||||
@ -16,6 +20,35 @@ from sshubl.st_utils import (
|
||||
class TestStUtils(unittest.TestCase):
|
||||
"""st_utils test cases"""
|
||||
|
||||
def test_get_command_class(self) -> None:
|
||||
"""get_command_class test cases"""
|
||||
|
||||
class TestFakeCommand(sublime_plugin.WindowCommand):
|
||||
pass
|
||||
|
||||
window_command_classes_mock = MagicMock()
|
||||
window_command_classes_mock.__iter__.return_value = [
|
||||
TestFakeCommand,
|
||||
SshTerminalCommand,
|
||||
]
|
||||
|
||||
with patch(
|
||||
"sshubl.st_utils.sublime_plugin.window_command_classes", window_command_classes_mock
|
||||
):
|
||||
# unknown command, looked up twice
|
||||
self.assertIsNone(get_command_class("_UnknownCommand"))
|
||||
self.assertIsNone(get_command_class("_UnknownCommand"))
|
||||
self.assertEqual(window_command_classes_mock.__iter__.call_count, 2)
|
||||
|
||||
window_command_classes_mock.reset_mock()
|
||||
|
||||
# SSHubl own `ssh_terminal` command, looked up and found once
|
||||
self.assertIs(get_command_class("SshTerminalCommand"), SshTerminalCommand)
|
||||
self.assertIs(get_command_class("SshTerminalCommand"), SshTerminalCommand)
|
||||
self.assertEqual(window_command_classes_mock.__iter__.call_count, 1)
|
||||
|
||||
window_command_classes_mock.reset_mock()
|
||||
|
||||
def test_format_ip_addr(self) -> None:
|
||||
"""format_ip_addr test cases"""
|
||||
self.assertEqual(format_ip_addr("127.0.0.1"), "127.0.0.1")
|
||||
|
Loading…
x
Reference in New Issue
Block a user