2 Commits
Author SHA1 Message Date
ge a34efe4e4e fix remaining tests, bump version 2026-09-24 23:28:11 +03:00
ge 917b47c94a ci: Add CI 2026-01-01 04:50:39 +03:00
5 changed files with 128 additions and 15 deletions
+48
View File
@@ -0,0 +1,48 @@
name: Docs
on:
push:
branches: [ "master" ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup V
run: |
wget -qO /tmp/v.zip https://github.com/vlang/v/releases/latest/download/v_linux.zip
unzip -q /tmp/v.zip -d /tmp
echo /tmp/v >> "$GITHUB_PATH"
- name: Build docs
run: |
v doc -f html -m .
pushd _docs
ln -vs ${{ github.event.repository.name }}.html index.html
ls -alFh
popd
- name: Upload static files as artifact
id: deployment
uses: actions/upload-pages-artifact@v3
with:
path: _docs/
deploy:
needs: build
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
permissions:
contents: read
pages: write
id-token: write
+27
View File
@@ -0,0 +1,27 @@
name: Lint and test
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
workflow_dispatch:
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup V
run: |
wget -qO /tmp/v.zip https://github.com/vlang/v/releases/latest/download/v_linux.zip
unzip -q /tmp/v.zip -d /tmp
echo /tmp/v >> "$GITHUB_PATH"
- name: Run tests
run: |
v fmt -verify .
v vet -v -W -I -F -r .
v missdoc -r --verify .
v -stats test .
+48 -9
View File
@@ -8,7 +8,7 @@ pub const safe_chars = '%+,-./0123456789:=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghij
// special_chars contains ASCII characters that must be escaped in shell.
pub const special_chars = ' \$"\'\\!'
const special_chars_runes = [` `, `$`, `"`, `'`, `\``, `\\`, `!`]
const special_chars_runes = [` `, `$`, `"`, `'`, `\``, `\\`, `!`]!
// quote returns a quoted version of string `s`.
//
@@ -163,12 +163,14 @@ fn parse(line string) ![]string {
mut single_quoted := false
mut double_quoted := false
mut back_quoted := false
mut dollar_quoted := false
mut dollar_depth := 0
mut commented := false
mut got := Mode.no
for i, c in line {
mut r := c
dollar_quoted := dollar_depth > 0
if escaped {
if r == `t` {
@@ -177,8 +179,14 @@ fn parse(line string) ![]string {
if r == `n` {
r = `\n`
}
buf << r
escaped = false
if commented {
if r == `\n` {
commented = false
}
continue
}
buf << r
got = .normal
continue
}
@@ -199,6 +207,36 @@ fn parse(line string) ![]string {
continue
}
if commented {
if r == `\n` {
commented = false
}
continue
}
if r == `#` && !single_quoted && !double_quoted && !back_quoted && !dollar_quoted {
// Everything up to the end of the line is a comment. The word being
// accumulated, if any, is terminated by it.
if got != .no {
tokens << buf.bytestr()
buf = []u8{}
got = .no
}
commented = true
continue
}
if r == `;` && !single_quoted && !double_quoted && !back_quoted && !dollar_quoted {
// Command separator is a token on its own.
if got != .no {
tokens << buf.bytestr()
buf = []u8{}
}
tokens << ';'
got = .no
continue
}
if r.is_space() {
if single_quoted || double_quoted || back_quoted || dollar_quoted {
buf << r
@@ -217,17 +255,18 @@ fn parse(line string) ![]string {
}
}
`(` {
if !single_quoted && !double_quoted && !dollar_quoted {
if !dollar_quoted && buf.len - 1 >= 0 && buf[buf.len - 1..][0] == `$` {
dollar_quoted = true
if !single_quoted && !double_quoted {
// Opens a `$(` expression or nests inside an already opened one.
if dollar_quoted || (buf.len > 0 && buf.last() == `$`) {
dollar_depth++
buf << r
continue
}
}
}
`)` {
if !single_quoted && !double_quoted && !dollar_quoted {
dollar_quoted = false
if !single_quoted && !double_quoted && dollar_quoted {
dollar_depth--
}
}
`"` {
@@ -264,7 +303,7 @@ fn parse(line string) ![]string {
single_quoted { return error('non-terminated quote in string') }
double_quoted { return error('non-terminated double quote in string') }
back_quoted { return error('non-terminated backtick in string') }
dollar_quoted { return error('non-terminated dollar expression in string') }
dollar_depth > 0 { return error('non-terminated dollar expression in string') }
else {}
}
+4 -5
View File
@@ -30,7 +30,6 @@ fn test_strip_ansi_escape_codes() {
}
// Original test data taken from https://github.com/python/cpython/blob/3.14/Lib/test/test_shlex.py
// FIXME: All test-cases must pass.
// vfmt off
const test_data = {
'foo': ['foo']
@@ -90,10 +89,10 @@ const test_data = {
'":-) ;-)"': [':-) ;-)']
'foo `bar baz`': ['foo', '`bar baz`']
r'foo "$(bar baz)"': ['foo', r'$(bar baz)']
// r'foo $(bar)': ['foo', r'$(bar)'] // failing
// r'foo $(bar baz)': ['foo', r'$(bar baz)'] // failing
// r'foo#bar\nbaz': ['foo', 'baz'] // failing
// 'foo;bar': ['foo', ';', 'bar'] // failing
r'foo $(bar)': ['foo', r'$(bar)']
r'foo $(bar baz)': ['foo', r'$(bar baz)']
r'foo#bar\nbaz': ['foo', 'baz']
'foo;bar': ['foo', ';', 'bar']
'"foo\\\\\\x bar\\" df\'a\\ \'df"': ['foo\\\\x bar" df\'a\\ \'df']
'"foo\\ x\\x\\\\"\\\'"foobar"': [r"foo\ x\x\'foobar"]
+1 -1
View File
@@ -1,7 +1,7 @@
Module {
name: 'shellish'
description: 'Shell-like syntax parser and text processor'
version: '0.1.0'
version: '0.1.1'
license: 'MIT'
dependencies: []
}