Skip to content

Commit

Permalink
Add vim and neovim syntax
Browse files Browse the repository at this point in the history
Ref. eng/recordflux/RecordFlux#1749
  • Loading branch information
Volham22 committed Aug 28, 2024
1 parent 90454fe commit 9f5ac97
Show file tree
Hide file tree
Showing 7 changed files with 361 additions and 4 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- Vim and Neovim syntax highlighting support (eng/recordflux/RecordFlux#1749)

### Changed

- Improve generation of predicate for single-field messages (eng/recordflux/RecordFlux#1761)
Expand Down
4 changes: 2 additions & 2 deletions doc/user_guide/90-rflx-install--help.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
usage: rflx install [-h] [--gnat-studio-dir GNAT_STUDIO_DIR]
{gnatstudio,vscode}
{gnatstudio,vscode,nvim,vim}

positional arguments:
{gnatstudio,vscode}
{gnatstudio,vscode,nvim,vim}

options:
-h, --help show this help message and exit
Expand Down
5 changes: 3 additions & 2 deletions pyproject.toml.in
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ packages = [
{ include = "rflx" },
]
include = [
{ path = "Cargo.lock", format = "sdist" },
{ path = "Cargo.toml", format = "sdist" },
{ path = "generated/adasat/*.gpr", format = "sdist" },
{ path = "generated/adasat/src/*.ad?", format = "sdist" },
{ path = "generated/gnatcoll-bindings/gmp/*.ad?", format = "sdist" },
Expand All @@ -46,14 +48,13 @@ include = [
{ path = "generated/langkit/langkit/support/*.gpr", format = "sdist" },
{ path = "generated/librflxlang.gpr", format = "sdist" },
{ path = "generated/src/*", format = "sdist" },
{ path = "Cargo.lock", format = "sdist" },
{ path = "Cargo.toml", format = "sdist" },
{ path = "librapidflux/Cargo.toml", format = "sdist" },
{ path = "librapidflux/src/*.rs", format = "sdist" },
{ path = "librapidflux/src/diagnostics/*.rs", format = "sdist" },
{ path = "rapidflux/Cargo.toml", format = "sdist" },
{ path = "rapidflux/src/*.rs", format = "sdist" },
{ path = "rapidflux/src/diagnostics/*.rs", format = "sdist" },
{ path = "rflx/ide/vim/recordflux.vim" },
{ path = "rflx/ide/vscode/recordflux.vsix" },
{ path = "rflx/lang/__init__.py" },
{ path = "rflx/lang/py.typed" },
Expand Down
69 changes: 69 additions & 0 deletions rflx/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
class IDE(Enum):
GNATSTUDIO = "gnatstudio"
VSCODE = "vscode"
NVIM = "nvim"
VIM = "vim"

def __str__(self) -> str:
return self.value
Expand Down Expand Up @@ -627,6 +629,34 @@ def validate(args: argparse.Namespace) -> None:
raise fatal_error from e


def install_vim_ftdetect(config_dir: Path, editor: str) -> None:
ftdetect_dir = config_dir / "ftdetect"
ftdetect_file = ftdetect_dir / "recordflux.vim"
ftdetect_dir.mkdir(parents=True, exist_ok=True)
ftdetect_file.write_text("autocmd BufRead,BufNewFile *.rflx set filetype=recordflux\n")

logging.info('Installed {editor} ftdetect file in "{path}"', editor=editor, path=ftdetect_file)


def install_syntax_file(config_dir: Path, editor: str) -> None:
syntax_dir = config_dir / "syntax"
syntax_dir.mkdir(parents=True, exist_ok=True)
with importlib_resources.as_file(vim_syntax_file()) as syntax_file:
file_path = syntax_dir / syntax_file.name

shutil.copy(syntax_file, file_path)

logging.info('Installed {editor} syntax file in "{path}"', editor=editor, path=file_path)


def install_vim_files(config_dir: Path, editor: str) -> None:
try:
install_vim_ftdetect(config_dir, editor)
install_syntax_file(config_dir, editor)
except OSError as e:
fail(f'failed to install {editor} files: "{e}"')


def install(args: argparse.Namespace) -> None:
if args.ide is IDE.GNATSTUDIO:
# TODO(eng/recordflux/RecordFlux#1359): Replace importlib_resources by importlib.resources
Expand All @@ -644,6 +674,39 @@ def install(args: argparse.Namespace) -> None:
except (FileNotFoundError, subprocess.CalledProcessError) as e:
fail(f"installation of VS Code extension failed: {e}")

elif args.ide is IDE.NVIM:
home_dir = os.environ.get("HOME")
xdg_config_home = os.environ.get("XDG_CONFIG_HOME")
if home_dir is None and xdg_config_home is None:
RecordFluxError(
[
ErrorEntry("could not find config directory", Severity.ERROR),
ErrorEntry(
"make sure $HOME or $XDG_CONFIG_HOME variable is set",
Severity.HELP,
),
],
).propagate()

if xdg_config_home is not None:
config_path = Path(xdg_config_home) / "nvim"
else:
assert home_dir is not None
config_path = Path(home_dir) / ".config" / "nvim"

install_vim_files(config_path, editor="nvim")

elif args.ide is IDE.VIM:
home_dir = os.environ.get("HOME")
if home_dir is None:
RecordFluxError(
[
ErrorEntry("could not locate home directory", Severity.ERROR),
ErrorEntry("make sure $HOME variable is set", Severity.HELP),
],
).propagate()
assert home_dir is not None
install_vim_files(Path(home_dir) / ".vim", editor="vim")
else:
assert_never(args.ide) # pragma: no cover

Expand Down Expand Up @@ -673,5 +736,11 @@ def vscode_extension() -> Traversable:
return path


def vim_syntax_file() -> Traversable:
path = importlib_resources.files("rflx") / "ide" / "vim" / "recordflux.vim"
assert isinstance(path, Traversable)
return path


def cache(no_caching: bool, no_verification: bool) -> Cache:
return NeverVerify() if no_verification else (AlwaysVerify() if no_caching else Cache())
133 changes: 133 additions & 0 deletions rflx/ide/vim/recordflux.vim
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
" Keywords
syntax keyword rflxKeyword with
syntax keyword rflxKeyword package
syntax keyword rflxKeyword is
syntax keyword rflxKeyword type
syntax keyword rflxKeyword range
syntax keyword rflxKeyword all
syntax keyword rflxKeyword some
syntax keyword rflxKeyword Head
syntax match rflxKeyword "'"
syntax keyword rflxKeyword null
syntax keyword rflxKeyword message
syntax keyword rflxKeyword case
syntax keyword rflxKeyword when
syntax keyword rflxKeyword First
syntax keyword rflxKeyword Size
syntax keyword rflxKeyword Last
syntax match rflxKeyword "[.]\\{2,\\}"
syntax match rflxKeyword "Always_Valid"
syntax keyword rflxKeyword end
syntax keyword rflxKeyword Checksum
syntax match rflxKeyword "Byte_Order"
syntax match rflxKeyword "High_Order_First"
syntax match rflxKeyword "Low_Order_First"
syntax keyword rflxKeyword use
syntax keyword rflxKeyword new
syntax keyword rflxKeyword sequence
syntax keyword rflxKeyword of
syntax keyword rflxKeyword generic
syntax keyword rflxKeyword function
syntax keyword rflxKeyword return
syntax keyword rflxKeyword Channel
syntax keyword rflxKeyword Readable
syntax keyword rflxKeyword Writable
syntax keyword rflxKeyword session
syntax keyword rflxKeyword renames
syntax keyword rflxKeyword begin
syntax keyword rflxKeyword state
syntax keyword rflxKeyword Desc
syntax keyword rflxKeyword Append
syntax keyword rflxKeyword Extend
syntax keyword rflxKeyword Reset
syntax keyword rflxKeyword Read
syntax keyword rflxKeyword Write
syntax keyword rflxKeyword transition
syntax keyword rflxKeyword goto
syntax keyword rflxKeyword exception
hi link rflxKeyword Keyword

" Conditional keywords
syntax keyword rflxConditional if
syntax keyword rflxConditional then
hi link rflxConditional Conditional

" Punctuation (neovim specific). See `:h treesitter-highlight`
if has('nvim-0.9')
syntax match rflxPunctuation ";"
syntax match rflxPunctuation "("
syntax match rflxPunctuation ")"
syntax match rflxPunctuation "\["
syntax match rflxPunctuation "]"
syntax match rflxPunctuation ","
syntax match rflxPunctuation "[.]"
syntax match rflxPunctuation ":"
hi link rflxPunctuation @punctuation
endif

" Operators
syntax match rflxOperator "=>"
syntax match rflxOperator ":="
syntax match rflxOperator "+"
syntax match rflxOperator "-"
syntax match rflxOperator "[*]"
syntax match rflxOperator "[.]\{2,}"
syntax match rflxOperator "/"
syntax keyword rflxOperator mod
syntax match rflxOperator ":\{2,}"
syntax keyword rflxOperator and
syntax keyword rflxOperator or
syntax keyword rflxOperator not
syntax keyword rflxOperator Valid
syntax match rflxOperator "Has_Data"
syntax keyword rflxOperator Present
syntax match rflxOperator "="
syntax match rflxOperator "/="
syntax match rflxOperator "<="
syntax match rflxOperator "<"
syntax match rflxOperator ">="
syntax match rflxOperator ">"
syntax keyword rflxOperator for
syntax keyword rflxOperator in
syntax match rflxOperator "\""
syntax match rflxOperator "not in"
syntax match rflxOperator "|"
syntax match rflxOperator "[*]\{2,}"
syntax match rflxOperator "Valid_Checksum"
hi link rflxOperator Operator

" Boolean constants
syntax keyword rflxBoolean True
syntax keyword rflxBoolean False
hi link rflxBoolean Boolean

" Builtin types
syntax keyword rflxType Opaque
syntax keyword rflxType Boolean
hi link rflxType Type

" Match number literal such as `1` or in an explicit base `#16#FF#`
syntax match rflxNumber "\<\d[0-9_]*\(\.\d[0-9_]*\)\=\([Ee][+-]\=\d[0-9_]*\)\=\>"
syntax match rflxNumber
\ "\<\d\d\=#\x[0-9A-Fa-f_]*\(\.\x[0-9A-Fa-f_]*\)\=#\([Ee][+-]\=\d[0-9_]*\)\="
hi link rflxNumber Number

" TODO, FIXME, NOTE and XXX
syntax keyword rflxTodo contained TODO FIXME XXX NOTE
hi link rflxTodo Todo

" Comments
syntax region rflxComment
\ oneline
\ contains=rflxTodo
\ start="--"
\ end="$"
hi link rflxComment Comment

" String literals (e.g. "some text")
syntax region rflxString
\ oneline
\ contains=rflxTodo
\ start="\""
\ end="\""
hi link rflxString String
24 changes: 24 additions & 0 deletions tests/ide/vim_syntax_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from __future__ import annotations

import subprocess
from pathlib import Path

import pytest

SYNTAX_FILE = Path("rflx/ide/vim/recordflux.vim")


@pytest.mark.parametrize(
"args",
[
(["vim", "--not-a-term"]),
(["nvim", "--headless"]),
],
)
def test_vim_syntax_source(args: list[str]) -> None:
ret = subprocess.run(
[*args, "-c", f":source {SYNTAX_FILE}", "-c", ":quit"],
check=False,
stderr=subprocess.PIPE,
)
assert ret.stderr.decode() == ""
Loading

0 comments on commit 9f5ac97

Please sign in to comment.