From aec52ecf33313554cfc6bfd7d8d824b14e5b96d2 Mon Sep 17 00:00:00 2001 From: Moosems <95927277+Moosems@users.noreply.github.com> Date: Thu, 1 Aug 2024 13:47:39 -0600 Subject: [PATCH] V1.1.0 (#83) * V1.1.0 version bump * Add to do (#80) * Combine worfklows (#82) * Combine worfklows * Try caching the os and packages Trying to reduce time for workflows * Revert "Try caching the os and packages" This reverts commit 9a67adc95c0f485e78cea47fca28984483e002c5. * Remove black formatting Keep ruff formatting though * Remove black from requirements * Collegamento ipc (#85) * Implement Request wrappers * Use collegamento * Format * Add requirement --- .github/PULL_REQUEST_TEMPLATE.md | 5 +- .github/workflows/black.yml | 17 --- .github/workflows/format.yml | 43 ++++++ .github/workflows/isort.yml | 17 --- .github/workflows/ruff-format.yml | 17 --- .github/workflows/ruff.yml | 17 --- .github/workflows/tests.yml | 30 +++- .github/workflows/windows-tests.yml | 18 --- README.md | 2 +- docs/source/conf.py | 2 +- requirements-dev.txt | 2 +- requirements.txt | 1 + salve/__init__.py | 3 +- salve/ipc.py | 227 +++++----------------------- salve/misc.py | 54 ------- salve/server.py | 205 ------------------------- salve/wrappers.py | 56 +++++++ setup.py | 2 +- 18 files changed, 181 insertions(+), 537 deletions(-) delete mode 100644 .github/workflows/black.yml create mode 100644 .github/workflows/format.yml delete mode 100644 .github/workflows/isort.yml delete mode 100644 .github/workflows/ruff-format.yml delete mode 100644 .github/workflows/ruff.yml delete mode 100644 .github/workflows/windows-tests.yml delete mode 100644 salve/server.py create mode 100644 salve/wrappers.py diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0e4988b..127a43f 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,4 +1,7 @@ Fixes #__. -Changes in PR: +To do: + - [ ] ... + +Cuurent changes in PR: - ... diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml deleted file mode 100644 index 267683f..0000000 --- a/.github/workflows/black.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Black Formatting - -on: push - -jobs: - formatting-black: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: 3.11.1 - - - name: Code Formatting (App) - run: | - pip install -r requirements-dev.txt - black --check . diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..a116b10 --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,43 @@ +name: Formatting + +on: push + +jobs: + formatting-isort: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.11.1 + + - name: Code Formatting (App) + run: | + pip install -r requirements-dev.txt + isort --check . + + formatting-ruff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.11.1 + + - name: Code Formatting (App) + run: | + pip install -r requirements-dev.txt + ruff format --check . + + ruff-check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.11.1 + + - name: Code Formatting (App) + run: | + pip install -r requirements-dev.txt + ruff check . diff --git a/.github/workflows/isort.yml b/.github/workflows/isort.yml deleted file mode 100644 index 3257dc9..0000000 --- a/.github/workflows/isort.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Isort Formatting - -on: push - -jobs: - formatting-isort: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: 3.11.1 - - - name: Code Formatting (App) - run: | - pip install -r requirements-dev.txt - isort --check . diff --git a/.github/workflows/ruff-format.yml b/.github/workflows/ruff-format.yml deleted file mode 100644 index 16adc33..0000000 --- a/.github/workflows/ruff-format.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Ruff Formatting - -on: push - -jobs: - formatting-ruff: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: 3.11.1 - - - name: Code Formatting (App) - run: | - pip install -r requirements-dev.txt - ruff format --check . diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml deleted file mode 100644 index 98f68b8..0000000 --- a/.github/workflows/ruff.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Ruff Check - -on: push - -jobs: - ruff-check: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: 3.11.1 - - - name: Code Formatting (App) - run: | - pip install -r requirements-dev.txt - ruff check . diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index afc9074..427337c 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -3,7 +3,7 @@ name: Code Tests on: push jobs: - testing: + testing-ubuntu: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -16,3 +16,31 @@ jobs: pip install . pip install -r requirements-dev.txt python3 -m pytest . + + testing-macos: + runs-on: macos-13 + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.11.1 + + - name: Run tests + run: | + pip install . + pip install -r requirements-dev.txt + python3 -m pytest . + + testing-windows: + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - uses: actions/setup-python@v2 + with: + python-version: 3.11.1 + + - name: Run tests + run: | + pip install . + pip install -r requirements-dev.txt + python3 -m pytest . -s diff --git a/.github/workflows/windows-tests.yml b/.github/workflows/windows-tests.yml deleted file mode 100644 index 25e1368..0000000 --- a/.github/workflows/windows-tests.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: Code Tests (On Windows) - -on: push - -jobs: - testing-windows: - runs-on: windows-latest - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-python@v2 - with: - python-version: 3.11.1 - - - name: Run tests - run: | - pip install . - pip install -r requirements-dev.txt - python3 -m pytest . -s diff --git a/README.md b/README.md index 2a37c7d..0aa0c13 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -

Salve v1.0.0

+

Salve v1.1.0

# Installation diff --git a/docs/source/conf.py b/docs/source/conf.py index 9996395..617ee17 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -14,7 +14,7 @@ project = "Salve" copyright = "2024, Moosems" author = "Moosems" -release = "v1.0.0" +release = "v1.1.0" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration diff --git a/requirements-dev.txt b/requirements-dev.txt index bca0199..2cd615e 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -3,6 +3,7 @@ pygments pyeditorconfig beartype token_tools +collegamento # Testing pytest @@ -10,7 +11,6 @@ pytest # Formatting ruff isort -black # Builds setuptools diff --git a/requirements.txt b/requirements.txt index fcb8d86..7bafcad 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,3 +2,4 @@ pygments pyeditorconfig beartype token_tools +collegamento diff --git a/salve/__init__.py b/salve/__init__.py index b8c1652..3630c1e 100644 --- a/salve/__init__.py +++ b/salve/__init__.py @@ -2,6 +2,8 @@ beartype_this_package() +from collegamento import Response # noqa: F401, E402 + from .ipc import IPC # noqa: F401, E402 from .misc import ( # noqa: F401, E402 AUTOCOMPLETE, @@ -11,6 +13,5 @@ HIGHLIGHT, LINKS_AND_CHARS, REPLACEMENTS, - Response, ) from .server_functions import is_unicode_letter # noqa: F401, E402 diff --git a/salve/ipc.py b/salve/ipc.py index b408a6b..df81385 100644 --- a/salve/ipc.py +++ b/salve/ipc.py @@ -1,113 +1,51 @@ -from logging import Logger, getLogger -from multiprocessing import Process, Queue, freeze_support from pathlib import Path -from random import randint + +from collegamento import FileClient from .misc import ( + AUTOCOMPLETE, COMMAND, COMMANDS, + DEFINITION, EDITORCONFIG, - Notification, - Request, - RequestQueueType, - Response, - ResponseQueueType, + HIGHLIGHT, + LINKS_AND_CHARS, + REPLACEMENTS, +) +from .wrappers import ( + editorconfig_request_wrapper, + find_autocompletions_request_wrapper, + get_definition_request_wrapper, + get_highlights_request_wrapper, + get_replacements_request_wrapper, + get_special_tokens_request_wrapper, ) -from .server import Server -class IPC: +class IPC(FileClient): """The IPC class is used to talk to the server and run commands. The public API includes the following methods: - IPC.request() - - IPC.cancel_request() - IPC.update_file() - IPC.remove_file() - IPC.kill_IPC() """ - def __init__(self, id_max: int = 15_000) -> None: - self.all_ids: list[int] = [] - self.id_max = id_max - self.current_ids: dict[str, int] = {} - self.newest_responses: dict[str, Response | None] = {} - for command in COMMANDS: - self.current_ids[command] = 0 - self.newest_responses[command] = None - - self.files: dict[str, str] = {} - - self.logger: Logger = getLogger("IPC") - self.logger.info("Creating server") - self.response_queue: ResponseQueueType = Queue() - self.requests_queue: RequestQueueType = Queue() - self.main_server: Process - self.create_server() - self.logger.info("Initialization is complete") - - def create_server(self) -> None: - """Creates the main_server through a subprocess - internal API""" - freeze_support() - server_logger = getLogger("Server") - self.main_server = Process( - target=Server, - args=(self.response_queue, self.requests_queue, server_logger), - daemon=True, + def __init__(self, id_max: int = 15000) -> None: + super().__init__( + id_max=id_max, + commands={ + AUTOCOMPLETE: find_autocompletions_request_wrapper, + REPLACEMENTS: get_replacements_request_wrapper, + HIGHLIGHT: get_highlights_request_wrapper, + EDITORCONFIG: editorconfig_request_wrapper, + DEFINITION: get_definition_request_wrapper, + LINKS_AND_CHARS: get_special_tokens_request_wrapper, + }, ) - self.main_server.start() - self.logger.info("Server created") - - self.logger.info("Copying files to server") - files_copy = self.files.copy() - self.files = {} - for file, data in files_copy.items(): - self.update_file(file, data) - self.logger.debug("Finished copying files to server") - - def create_message(self, type: str, **kwargs) -> None: - """Creates a Message based on the args and kwawrgs provided. Highly flexible. - internal API""" - self.logger.info("Creating message for server") - id = randint(1, self.id_max) # 0 is reserved for the empty case - while id in self.all_ids: - id = randint(1, self.id_max) - self.all_ids.append(id) - - self.logger.debug("ID for message created") - if not self.main_server.is_alive(): - self.logger.critical( - "Server was killed at some point, creating server" - ) - self.create_server() - - match type: - case "request": - self.logger.info("Creating request for server") - command = kwargs.get("command", "") - self.current_ids[command] = id - request: Request = { - "id": id, - "type": type, - "command": command, - "file": "", - } - request.update(**kwargs) - self.logger.debug(f"Request created: {request}") - self.requests_queue.put(request) - self.logger.info("Message sent") - case "notification": - self.logger.info("Creating notification for server") - notification: Notification = { - "id": id, - "type": type, - "remove": False, - "file": "", - "contents": "", - } - notification.update(**kwargs) - self.logger.debug(f"Notification created: {notification}") - self.requests_queue.put(notification) - self.logger.info("Message sent") - def request( + # Pyright likes to complain and say this won't work but it actually does + # TODO: Use plum or custom multiple dispatch (make it a new project for salve organization) + def request( # type: ignore self, command: COMMAND, file: str = "", @@ -133,96 +71,15 @@ def request( raise Exception(f"File {file} does not exist in system!") self.logger.debug("Sending info to create_message()") - self.create_message( - type="request", - command=command, - file=file, - expected_keywords=expected_keywords, - current_word=current_word, - language=language, - text_range=text_range, - file_path=file_path, - definition_starters=definition_starters, - ) - - def cancel_request(self, command: str) -> None: - """Cancels a request of type command - external API""" - if command not in COMMANDS: - self.logger.exception( - f"Cannot cancel command {command}, valid commands are {COMMANDS}" - ) - raise Exception( - f"Cannot cancel command {command}, valid commands are {COMMANDS}" - ) - - self.logger.info(f"Cancelled command: {command}") - self.current_ids[command] = 0 - - def parse_response(self, res: Response) -> None: - """Parses main_server output line and discards useless responses - internal API""" - self.logger.debug("Parsing server response") - id = res["id"] - self.all_ids.remove(id) - - if "command" not in res: - self.logger.info("Response was notification response") - return - - command = res["command"] - if id != self.current_ids[command]: - self.logger.info("Response is from old request") - return - - self.logger.info(f"Response is useful for command type: {command}") - self.current_ids[command] = 0 - self.newest_responses[command] = res - - def check_responses(self) -> None: - """Checks all main_server output by calling IPC.parse_line() on each response - internal API""" - self.logger.debug("Checking responses") - while not self.response_queue.empty(): - self.parse_response(self.response_queue.get()) - - def get_response(self, command: str) -> Response | None: - """Checks responses and returns the current response of type command if it has been returned - external API""" - self.logger.info(f"Getting response for type: {command}") - if command not in COMMANDS: - self.logger.exception( - f"Cannot get response of command {command}, valid commands are {COMMANDS}" - ) - raise Exception( - f"Cannot get response of command {command}, valid commands are {COMMANDS}" - ) - - self.check_responses() - response: Response | None = self.newest_responses[command] - self.newest_responses[command] = None - self.logger.info("Response retrieved") - return response - - def update_file(self, file: str, current_state: str) -> None: - """Updates files in the system - external API""" - - self.logger.info(f"Updating file: {file}") - self.files[file] = current_state - - self.logger.debug("Notifying server of file update") - self.create_message("notification", file=file, contents=current_state) - - def remove_file(self, file: str) -> None: - """Removes a file from the main_server - external API""" - if file not in list(self.files.keys()): - self.logger.exception( - f"Cannot remove file {file} as file is not in file database!" - ) - raise Exception( - f"Cannot remove file {file} as file is not in file database!" - ) - - self.logger.info("Notifying server of file deletion") - self.create_message("notification", remove=True, file=file) - - def kill_IPC(self) -> None: - """Kills the main_server when salve_ipc's services are no longer required - external API""" - self.logger.info("Killing server") - self.main_server.kill() + request: dict = { + "command": command, + "expected_keywords": expected_keywords, + "current_word": current_word, + "language": language, + "text_range": text_range, + "file_path": file_path, + "definition_starters": definition_starters, + } + if file: + request.update({"file": file}) + super().request(request) diff --git a/salve/misc.py b/salve/misc.py index d70b792..0949244 100644 --- a/salve/misc.py +++ b/salve/misc.py @@ -1,9 +1,3 @@ -from multiprocessing.queues import Queue as GenericQueueClass -from pathlib import Path -from typing import TYPE_CHECKING, NotRequired, TypedDict - -from token_tools import Token - COMMANDS: list[str] = [ "autocomplete", "replacements", @@ -20,51 +14,3 @@ EDITORCONFIG: COMMAND = COMMANDS[3] DEFINITION: COMMAND = COMMANDS[4] LINKS_AND_CHARS: COMMAND = COMMANDS[5] - - -class Message(TypedDict): - """Base class for messages in and out of the server""" - - id: int - type: str # Can be "request", "response", "notification" - - -class Request(Message): - """Request results/output from the server with command specific input""" - - command: str # Can only be commands in COMMANDS - file: str - expected_keywords: NotRequired[list[str]] # autocomplete, replacements - current_word: NotRequired[str] # autocomplete, replacements, definition - language: NotRequired[str] # highlight - text_range: NotRequired[tuple[int, int]] # highlight, links_and_chars - file_path: NotRequired[Path | str] # editorconfig - definition_starters: NotRequired[ - list[tuple[str, str]] - ] # definition (list of regexes) - - -class Notification(Message): - """Notifies the server to add/update/remove a file for usage in fulfilling commands""" - - file: str - remove: bool - contents: NotRequired[str] - - -class Response(Message): - """Server responses to requests and notifications""" - - cancelled: bool - command: NotRequired[str] - result: NotRequired[list[str | Token] | dict[str, str] | Token] - - -if TYPE_CHECKING: - ResponseQueueType = GenericQueueClass[Response] - RequestQueueType = GenericQueueClass[Request | Notification] -# Else, this is CPython < 3.12. We are now in the No Man's Land -# of Typing. In this case, avoid subscripting "GenericQueue". Ugh. -else: - ResponseQueueType = GenericQueueClass - RequestQueueType = GenericQueueClass diff --git a/salve/server.py b/salve/server.py deleted file mode 100644 index 5a83b2c..0000000 --- a/salve/server.py +++ /dev/null @@ -1,205 +0,0 @@ -from logging import Logger -from multiprocessing.queues import Queue as GenericClassQueue -from time import sleep - -from pyeditorconfig import get_config -from token_tools import Token, normal_text_range - -from .misc import ( - COMMANDS, - Notification, - Request, - RequestQueueType, - Response, - ResponseQueueType, -) -from .server_functions import ( - find_autocompletions, - get_definition, - get_highlights, - get_replacements, - get_special_tokens, -) - - -class Server: - """Handles input from the user and returns output from special functions. Not an external API.""" - - def __init__( - self, - response_queue: GenericClassQueue, - requests_queue: GenericClassQueue, - logger: Logger, - ) -> None: - self.logger: Logger = logger - self.logger.info("Starting server setup") - self.response_queue: ResponseQueueType = response_queue - self.requests_queue: RequestQueueType = requests_queue - self.all_ids: list[int] = [] - self.newest_ids: dict[str, int] = {} - self.newest_requests: dict[str, Request | None] = {} - for command in COMMANDS: - self.newest_ids[command] = 0 - self.newest_requests[command] = None - - self.files: dict[str, str] = {} - - self.logger.info("Server setup complete") - - while True: - self.run_tasks() - sleep(0.0025) - - def simple_id_response(self, id: int, cancelled: bool = True) -> None: - self.logger.debug(f"Creating simple response for id {id}") - response: Response = { - "id": id, - "type": "response", - "cancelled": cancelled, - } - self.logger.debug(f"Sending simple response for id {id}") - self.response_queue.put(response) - self.logger.info(f"Simple response for id {id} sent") - - def parse_line(self, message: Request | Notification) -> None: - self.logger.debug("Parsing Message from user") - id: int = message["id"] - match message["type"]: - case "notification": - self.logger.debug("Mesage is of type notification") - file: str = message["file"] # type: ignore - if message["remove"]: # type: ignore - self.logger.info(f"File {file} was requested for removal") - self.files.pop(file) - self.logger.info(f"File {file} has been removed") - return - contents: str = message["contents"] # type: ignore - self.files[file] = contents - self.logger.info( - f"File {file} has been updated with new contents" - ) - self.simple_id_response(id, False) - self.logger.debug( - f"Notification response for id {id} has been sent" - ) - case "request": - self.logger.info(f"Mesage with id {id} is of type request") - self.all_ids.append(id) - command: str = message["command"] # type: ignore - self.newest_ids[command] = id - self.newest_requests[command] = message # type: ignore - self.logger.debug("Request stored for parsing") - case _: - self.logger.warning( - f"Unknown type {type}. Sending simple response" - ) - self.simple_id_response(id) - self.logger.debug(f"Simple response for id {id} sent") - - def cancel_all_ids_except_newest(self) -> None: - self.logger.info("Cancelling all old id's") - ids = [ - id["id"] - for id in list(self.newest_requests.values()) - if id is not None - ] - for id in self.all_ids: - if id in ids: - self.logger.debug(f"Id {id} is newest of its command") - continue - self.logger.debug( - f"Id {id} is an old request, sending simple respone" - ) - self.simple_id_response(id) - - self.all_ids = [] - self.logger.debug("All ids list reset") - - def handle_request(self, request: Request) -> None: - command: str = request["command"] - id: int = self.newest_ids[command] - file: str = request["file"] - result: list[str | Token] | dict[str, str] = [] - cancelled: bool = False - - match request["command"]: - case "autocomplete": - self.logger.info("Finding completions for request") - result = find_autocompletions( - full_text=self.files[file], - expected_keywords=request["expected_keywords"], # type: ignore - current_word=request["current_word"], # type: ignore - ) - case "replacements": - self.logger.info("Getting replacements for request") - result = get_replacements( - full_text=self.files[file], - expected_keywords=request["expected_keywords"], # type: ignore - replaceable_word=request["current_word"], # type: ignore - ) - case "highlight": - self.logger.info("Getting normal highlights for request") - pre_refined_result: list[Token] = get_highlights( - full_text=self.files[file], - language=request["language"], # type: ignore - text_range=request["text_range"], # type: ignore - ) - result.extend([token for token in pre_refined_result]) - case "editorconfig": - self.logger.info("Getting editorconfig info for request") - result = get_config(request["file_path"]) # type: ignore - case "definition": - self.logger.info("Getting definition for request") - result = get_definition( - self.files[file], - request["definition_starters"], # type: ignore - request["current_word"], # type: ignore - ) - case "links_and_chars": - self.logger.info("Searching for Links and chars") - result = get_special_tokens( - self.files[file], - normal_text_range(self.files[file], request["text_range"])[ # type: ignore - 1 - ], - ) - case _: - self.logger.warning(f"Command {command} not recognized") - cancelled = True - - response: Response = { - "id": id, - "type": "response", - "cancelled": cancelled, - "command": command, - "result": result, - } - self.logger.debug("Response created") - self.response_queue.put(response) - self.newest_ids[command] = 0 - self.logger.info(f"Response sent for request of command {command}") - - def run_tasks(self) -> None: - if self.requests_queue.empty(): - return - - self.logger.debug("New request in queue") - while not self.requests_queue.empty(): - self.logger.debug("Parsing request") - self.parse_line(self.requests_queue.get()) - - if not self.all_ids: - self.logger.debug("All requests were notifications") - - self.logger.debug("Cancelling all old id's") - self.cancel_all_ids_except_newest() - - # Actual work - for request in list(self.newest_requests.values()): - if request is None: - continue - command: str = request["command"] - self.logger.info(f"Handling request of command {command}") - self.handle_request(request) - self.newest_requests[command] = None - self.logger.debug("Request completed") diff --git a/salve/wrappers.py b/salve/wrappers.py new file mode 100644 index 0000000..a8763c2 --- /dev/null +++ b/salve/wrappers.py @@ -0,0 +1,56 @@ +from collegamento import Request +from pyeditorconfig import get_config +from token_tools import Token, normal_text_range + +from .server_functions import ( + find_autocompletions, + get_definition, + get_highlights, + get_replacements, + get_special_tokens, +) + + +def find_autocompletions_request_wrapper(request: Request) -> list[str]: + return find_autocompletions( + full_text=request["file"], # type: ignore + expected_keywords=request["expected_keywords"], # type: ignore + current_word=request["current_word"], # type: ignore + ) + + +def get_replacements_request_wrapper(request: Request) -> list[str]: + return get_replacements( + full_text=request["file"], # type: ignore + expected_keywords=request["expected_keywords"], # type: ignore + replaceable_word=request["current_word"], # type: ignore + ) + + +def get_highlights_request_wrapper(request: Request) -> list[Token]: + return get_highlights( + full_text=request["file"], # type: ignore + language=request["language"], # type: ignore + text_range=request["text_range"], # type: ignore + ) + + +def editorconfig_request_wrapper(request: Request) -> dict: + return get_config(request["file_path"]) # type: ignore + + +def get_definition_request_wrapper(request: Request) -> Token: + return get_definition( + request["file"], # type: ignore + request["definition_starters"], # type: ignore + request["current_word"], # type: ignore + ) + + +def get_special_tokens_request_wrapper(request: Request) -> list[Token]: + return get_special_tokens( + request["file"], # type: ignore + normal_text_range(request["file"], request["text_range"])[ # type: ignore + 1 + ], + ) diff --git a/setup.py b/setup.py index 8f67330..71d3055 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name="salve", - version="1.0.0", + version="1.1.0", description="Salve is an IPC library that can be used by code editors to easily get autocompletions, replacements, editorconfig suggestions, definitions, and syntax highlighting.", author="Moosems", author_email="moosems.j@gmail.com",