Skip to content
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

Links and chars standalone #77

Merged
merged 6 commits into from
Jul 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/source/command-sheet.rst
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,9 @@ Below is a chart outlining the different request commands you can give and the d
current_word: ``str`` (the word being searched for),

definition_starters: ``list[tuple[str, str]]`` (list of regexes to search for and a string associated (see :doc:`examples/simple_definitions_example`))
* - ``LINKS_AND_CHARS``
- file: ``str``,

text_range: ``tuple[int, int]`` (the lower and upper line bounds (inclusively) of what text to highlight (optional))

To see how to use any given one of these in more detail, visit the :doc:`examples` page! Otherwise move on to the :doc:`special-classes` page instead.
31 changes: 31 additions & 0 deletions docs/source/examples/simple_links_and_hidden_chars_example.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
=====================================
Simple Links And Hidden Chars Example
=====================================

.. code-block:: python

from time import sleep

from salve import IPC, LINKS_AND_CHARS, Response


def main():
context = IPC()

context.update_file(
"test",
open(__file__, "r+").read(),
)

context.request(LINKS_AND_CHARS, file="test", text_range=(1, 30))

sleep(1)
output: Response | None = context.get_response(LINKS_AND_CHARS)
print(output)
context.kill_IPC()


if __name__ == "__main__":
main()

See the file example file `here <https://github.com/salve-org/salve/blob/master/examples/simple_links_and_hidden_chars_example.py>`_.
1 change: 1 addition & 0 deletions docs/source/variables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ The ``COMMAND`` variable is a ``str`` type alias's used to prevent spelling mist
- ``HIGHLIGHT``
- ``EDITORCONFIG``
- ``DEFINITION``
- ``LINKS_AND_CHARS``

.. _Hidden Chars Overview:

Expand Down
23 changes: 23 additions & 0 deletions examples/simple_links_and_hidden_chars_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from time import sleep

from salve import IPC, LINKS_AND_CHARS, Response


def main():
context = IPC()

context.update_file(
"test",
open(__file__, "r+").read(),
)

context.request(LINKS_AND_CHARS, file="test", text_range=(1, 30))

sleep(1)
output: Response | None = context.get_response(LINKS_AND_CHARS)
print(output)
context.kill_IPC()


if __name__ == "__main__":
main()
1 change: 1 addition & 0 deletions salve/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
DEFINITION,
EDITORCONFIG,
HIGHLIGHT,
LINKS_AND_CHARS,
REPLACEMENTS,
Response,
)
Expand Down
4 changes: 3 additions & 1 deletion salve/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"highlight",
"editorconfig",
"definition",
"links_and_chars",
]

COMMAND = str
Expand All @@ -18,6 +19,7 @@
HIGHLIGHT: COMMAND = COMMANDS[2]
EDITORCONFIG: COMMAND = COMMANDS[3]
DEFINITION: COMMAND = COMMANDS[4]
LINKS_AND_CHARS: COMMAND = COMMANDS[5]


class Message(TypedDict):
Expand All @@ -35,7 +37,7 @@ class Request(Message):
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
text_range: NotRequired[tuple[int, int]] # highlight, links_and_chars
file_path: NotRequired[Path | str] # editorconfig
definition_starters: NotRequired[
list[tuple[str, str]]
Expand Down
12 changes: 10 additions & 2 deletions salve/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from time import sleep

from pyeditorconfig import get_config
from token_tools import Token
from token_tools import Token, normal_text_range

from .misc import (
COMMANDS,
Expand All @@ -18,6 +18,7 @@
get_definition,
get_highlights,
get_replacements,
get_special_tokens,
)


Expand Down Expand Up @@ -154,7 +155,14 @@ def handle_request(self, request: Request) -> None:
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
Expand Down
1 change: 1 addition & 0 deletions salve/server_functions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .autocompletions import find_autocompletions # noqa: F401
from .definitions import get_definition # noqa: F401
from .highlight import get_highlights # noqa: F401
from .links_and_hidden_chars import get_special_tokens # noqa: F401
from .misc import is_unicode_letter # noqa: F401
from .replacements import get_replacements # noqa: F401
2 changes: 0 additions & 2 deletions salve/server_functions/highlight/highlight.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
)

from .docstring_highlight import _LexReturnTokens, proper_docstring_tokens
from .links_and_hidden_chars import get_special_tokens
from .misc import get_new_token_type


Expand Down Expand Up @@ -63,6 +62,5 @@ def get_highlights(
new_tokens, proper_docstring_tokens(lexer, full_text)
)

new_tokens.extend(get_special_tokens(full_text, split_text, text_range[0]))
new_tokens = only_tokens_in_text_range(new_tokens, text_range)
return new_tokens
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
url_regex: Pattern = compile(r"(ftp|http|https)://[a-zA-Z0-9_-]")


def get_urls(lines: list[str], start_line: int = 1) -> list[Token]:
start_pos: tuple[int, int] = (start_line, 0)
def get_urls(whole_text: str, text_range: tuple[int, int]) -> list[Token]:
lines: list[str] = whole_text.splitlines()
start_pos: tuple[int, int] = (text_range[0], 0)
url_toks: list[Token] = []
while True:
if start_pos[0] >= len(lines) + start_line:
if start_pos[0] > text_range[1]:
break
line: str = lines[start_pos[0] - start_line][start_pos[1] :]
line: str = lines[start_pos[0] - text_range[0]][start_pos[1] :]
match_start: Match[str] | None = url_regex.search(line)
if match_start is None:
start_pos = (start_pos[0] + 1, 0)
Expand Down Expand Up @@ -95,9 +96,12 @@ def get_urls(lines: list[str], start_line: int = 1) -> list[Token]:
}


def find_hidden_chars(lines: list[str], start_line: int = 1) -> list[Token]:
def find_hidden_chars(
whole_text: str, text_range: tuple[int, int]
) -> list[Token]:
lines: list[str] = whole_text.splitlines()
hidden_char_indexes: list[tuple[tuple[int, int], str]] = [
((line_index + start_line, char_index), char)
((line_index + text_range[0], char_index), char)
for line_index, line in enumerate(lines)
for char_index, char in enumerate(line)
if char in list(hidden_chars.keys())
Expand All @@ -109,11 +113,11 @@ def find_hidden_chars(lines: list[str], start_line: int = 1) -> list[Token]:


def get_special_tokens(
whole_text: str, split_text: list[str], start_offset: int
whole_text: str, text_range: tuple[int, int]
) -> list[Token]:
return_tokens: list[Token] = []
return_tokens.extend(get_urls(split_text, start_offset))
return_tokens.extend(get_urls(whole_text, text_range))
if [char for char in hidden_chars if char in whole_text]:
# If there are no hidden chars we don't want to needlessly compute this
return_tokens.extend(find_hidden_chars(split_text, start_offset))
return_tokens.extend(find_hidden_chars(whole_text, text_range))
return return_tokens
30 changes: 25 additions & 5 deletions tests/test_ipc.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
EDITORCONFIG,
HIGHLIGHT,
IPC,
LINKS_AND_CHARS,
REPLACEMENTS,
Response,
)
Expand Down Expand Up @@ -48,7 +49,7 @@ def test_IPC():
(r":?.*=.*", "before"),
],
)

context.request(LINKS_AND_CHARS, file="test", text_range=(1, 18))
sleep(1)

# Check output
Expand Down Expand Up @@ -118,11 +119,8 @@ def test_IPC():
((17, 0), 3, "Name"),
((17, 3), 2, "Punctuation"),
((18, 0), 24, "Comment"),
((18, 2), 22, "Link"),
((5, 7), 1, "Hidden_Char"),
],
}

# Deal with Windows weirdness
if platform == "win32":
expected_output = {
Expand Down Expand Up @@ -162,12 +160,34 @@ def test_IPC():
((17, 0), 3, "Name"),
((17, 3), 2, "Punctuation"),
((18, 0), 24, "Comment"),
((18, 2), 22, "Link"),
],
}

assert highlight_output == expected_output

links_and_hidden_chars_result: Response | None = context.get_response(
LINKS_AND_CHARS
)
if links_and_hidden_chars_result is None:
raise AssertionError("links_and_hidden_chars_result output is None")
links_and_hidden_chars_result["id"] = 0
expected_output = {
"id": 0,
"type": "response",
"cancelled": False,
"command": LINKS_AND_CHARS,
"result": [((18, 2), 22, "Link"), ((5, 7), 1, "Hidden_Char")],
}
if platform == "win32":
expected_output = {
"id": 0,
"type": "response",
"cancelled": False,
"command": LINKS_AND_CHARS,
"result": [((18, 2), 22, "Link")],
}
assert links_and_hidden_chars_result == expected_output

context.update_file(
"foo", open(Path("tests/testing_file2.py"), "r+").read()
)
Expand Down
Loading