From 8d83609a120d27b89e80828b4972408984ba56e2 Mon Sep 17 00:00:00 2001 From: DorZuberi Date: Mon, 30 Mar 2026 14:56:28 +0300 Subject: [PATCH] Add Bash language support with patterns and tests --- src/Highlighter.php | 4 +- src/Languages/Bash/BashLanguage.php | 72 +++++++++++++++++++ .../Bash/Patterns/BashBuiltinPattern.php | 33 +++++++++ .../Bash/Patterns/BashCommentPattern.php | 26 +++++++ .../Bash/Patterns/BashFlagPattern.php | 27 +++++++ .../Bash/Patterns/BashKeywordPattern.php | 35 +++++++++ .../Bash/Patterns/BashNumberPattern.php | 26 +++++++ .../Bash/Patterns/BashOperatorPattern.php | 27 +++++++ .../Bash/Patterns/BashShebangPattern.php | 27 +++++++ .../Bash/Patterns/BashVariablePattern.php | 27 +++++++ tests/Bench/Fixtures/bash.txt | 60 ++++++++++++++++ tests/Bench/HighlighterBench.php | 1 + tests/Languages/Bash/BashLanguageTest.php | 71 ++++++++++++++++++ 13 files changed, 435 insertions(+), 1 deletion(-) create mode 100644 src/Languages/Bash/BashLanguage.php create mode 100644 src/Languages/Bash/Patterns/BashBuiltinPattern.php create mode 100644 src/Languages/Bash/Patterns/BashCommentPattern.php create mode 100644 src/Languages/Bash/Patterns/BashFlagPattern.php create mode 100644 src/Languages/Bash/Patterns/BashKeywordPattern.php create mode 100644 src/Languages/Bash/Patterns/BashNumberPattern.php create mode 100644 src/Languages/Bash/Patterns/BashOperatorPattern.php create mode 100644 src/Languages/Bash/Patterns/BashShebangPattern.php create mode 100644 src/Languages/Bash/Patterns/BashVariablePattern.php create mode 100644 tests/Bench/Fixtures/bash.txt create mode 100644 tests/Languages/Bash/BashLanguageTest.php diff --git a/src/Highlighter.php b/src/Highlighter.php index 1374bd4..b253643 100644 --- a/src/Highlighter.php +++ b/src/Highlighter.php @@ -6,6 +6,7 @@ use ReflectionClass; use Tempest\Highlight\Languages\Base\Injections\GutterInjection; +use Tempest\Highlight\Languages\Bash\BashLanguage; use Tempest\Highlight\Languages\Blade\BladeLanguage; use Tempest\Highlight\Languages\Css\CssLanguage; use Tempest\Highlight\Languages\Diff\DiffLanguage; @@ -51,7 +52,8 @@ final class Highlighter public function __construct(private readonly Theme $theme = new CssTheme()) { - $this->addLanguage(new BladeLanguage()) + $this->addLanguage(new BashLanguage()) + ->addLanguage(new BladeLanguage()) ->addLanguage(new CssLanguage()) ->addLanguage(new DiffLanguage()) ->addLanguage(new DocCommentLanguage()) diff --git a/src/Languages/Bash/BashLanguage.php b/src/Languages/Bash/BashLanguage.php new file mode 100644 index 0000000..830ba7b --- /dev/null +++ b/src/Languages/Bash/BashLanguage.php @@ -0,0 +1,72 @@ +builtins); + + return "\b(?(?:{$builtins}))\b"; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::TYPE; + } +} \ No newline at end of file diff --git a/src/Languages/Bash/Patterns/BashCommentPattern.php b/src/Languages/Bash/Patterns/BashCommentPattern.php new file mode 100644 index 0000000..742b807 --- /dev/null +++ b/src/Languages/Bash/Patterns/BashCommentPattern.php @@ -0,0 +1,26 @@ +#.*)'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::COMMENT; + } +} \ No newline at end of file diff --git a/src/Languages/Bash/Patterns/BashFlagPattern.php b/src/Languages/Bash/Patterns/BashFlagPattern.php new file mode 100644 index 0000000..814c389 --- /dev/null +++ b/src/Languages/Bash/Patterns/BashFlagPattern.php @@ -0,0 +1,27 @@ +--?[a-zA-Z][\w-]*)'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::GENERIC; + } +} \ No newline at end of file diff --git a/src/Languages/Bash/Patterns/BashKeywordPattern.php b/src/Languages/Bash/Patterns/BashKeywordPattern.php new file mode 100644 index 0000000..9679c87 --- /dev/null +++ b/src/Languages/Bash/Patterns/BashKeywordPattern.php @@ -0,0 +1,35 @@ +keywords); + + return "\b(?(?:{$keywords}))\b"; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::KEYWORD; + } +} \ No newline at end of file diff --git a/src/Languages/Bash/Patterns/BashNumberPattern.php b/src/Languages/Bash/Patterns/BashNumberPattern.php new file mode 100644 index 0000000..2accaa8 --- /dev/null +++ b/src/Languages/Bash/Patterns/BashNumberPattern.php @@ -0,0 +1,26 @@ +\d+)\b'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::NUMBER; + } +} \ No newline at end of file diff --git a/src/Languages/Bash/Patterns/BashOperatorPattern.php b/src/Languages/Bash/Patterns/BashOperatorPattern.php new file mode 100644 index 0000000..82e60db --- /dev/null +++ b/src/Languages/Bash/Patterns/BashOperatorPattern.php @@ -0,0 +1,27 @@ +\|\||&&|>>|<<|;;|[|><;])'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::OPERATOR; + } +} \ No newline at end of file diff --git a/src/Languages/Bash/Patterns/BashShebangPattern.php b/src/Languages/Bash/Patterns/BashShebangPattern.php new file mode 100644 index 0000000..2b08c82 --- /dev/null +++ b/src/Languages/Bash/Patterns/BashShebangPattern.php @@ -0,0 +1,27 @@ +\#!\/.*)/'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::COMMENT; + } +} \ No newline at end of file diff --git a/src/Languages/Bash/Patterns/BashVariablePattern.php b/src/Languages/Bash/Patterns/BashVariablePattern.php new file mode 100644 index 0000000..c1076da --- /dev/null +++ b/src/Languages/Bash/Patterns/BashVariablePattern.php @@ -0,0 +1,27 @@ +\$\{[^}]+\}|\$[a-zA-Z_]\w*|\$[\d@?#!\$\-\*])'; + } + + public function getTokenType(): TokenTypeEnum + { + return TokenTypeEnum::VARIABLE; + } +} \ No newline at end of file diff --git a/tests/Bench/Fixtures/bash.txt b/tests/Bench/Fixtures/bash.txt new file mode 100644 index 0000000..a6a4381 --- /dev/null +++ b/tests/Bench/Fixtures/bash.txt @@ -0,0 +1,60 @@ +#!/bin/bash + +# Configuration +MAX_RETRIES=3 +LOG_FILE="/var/log/deploy.log" + +# Function to check service health +check_health() { + local url=$1 + local timeout=${2:-5} + + if curl --silent --fail --max-time "$timeout" "$url" > /dev/null 2>&1; then + echo "Service is healthy" + return 0 + else + echo "Service is not responding" >> "$LOG_FILE" + return 1 + fi +} + +# Deploy with retries +deploy() { + local attempt=1 + + while [ $attempt -le $MAX_RETRIES ]; do + echo "Deployment attempt $attempt of $MAX_RETRIES" + + if docker-compose up -d --build 2>&1 | tee -a "$LOG_FILE"; then + echo "Deployment successful" + break + fi + + attempt=$((attempt + 1)) + sleep 5 + done + + if [ $attempt -gt $MAX_RETRIES ]; then + echo "Deployment failed after $MAX_RETRIES attempts" >&2 + exit 1 + fi +} + +# Parse arguments +case "$1" in + start) + deploy + ;; + status) + check_health "http://localhost:8080/health" + ;; + *) + echo "Usage: $0 {start|status}" + exit 1 + ;; +esac + +for service in web api worker; do + printf "Checking %s...\n" "$service" + systemctl is-active --quiet "$service" && echo "OK" || echo "FAILED" +done \ No newline at end of file diff --git a/tests/Bench/HighlighterBench.php b/tests/Bench/HighlighterBench.php index 0516f96..2979dc3 100644 --- a/tests/Bench/HighlighterBench.php +++ b/tests/Bench/HighlighterBench.php @@ -17,6 +17,7 @@ final class HighlighterBench private const string FIXTURES_DIR = __DIR__ . '/Fixtures'; public const array LANGUAGES = [ + 'bash' => 'bash.txt', 'blade' => 'blade.txt', 'css' => 'css.txt', 'diff' => 'diff.txt', diff --git a/tests/Languages/Bash/BashLanguageTest.php b/tests/Languages/Bash/BashLanguageTest.php new file mode 100644 index 0000000..a025c89 --- /dev/null +++ b/tests/Languages/Bash/BashLanguageTest.php @@ -0,0 +1,71 @@ +assertSame( + $expected, + $highlighter->parse($content, 'bash'), + ); + + $this->assertSame( + $expected, + $highlighter->parse($content, 'sh'), + ); + + $this->assertSame( + $expected, + $highlighter->parse($content, 'shell'), + ); + } + + public static function provide_highlight_cases(): iterable + { + return [ + [<<<'TXT' +#!/bin/bash + +# Check if file exists +if [ -f "$1" ]; then + echo "File exists" + cat "$1" | wc -l +else + echo "File not found" >> /tmp/log + exit 1 +fi + +for i in 1 2 3; do + echo $i +done +TXT, + <<<'TXT' +#!/bin/bash + +# Check if file exists +if [ -f "$1" ]; then + echo "File exists" + cat "$1" | wc -l +else + echo "File not found" >> /tmp/log + exit 1 +fi + +for i in 1 2 3; do + echo $i +done +TXT], + ]; + } +} \ No newline at end of file