mirror of
https://github.com/gechandesu/shellish.git
synced 2026-10-05 00:46:47 +03:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a34efe4e4e | ||
|
|
917b47c94a |
@@ -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
|
||||||
@@ -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
@@ -8,7 +8,7 @@ pub const safe_chars = '%+,-./0123456789:=@ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghij
|
|||||||
// special_chars contains ASCII characters that must be escaped in shell.
|
// special_chars contains ASCII characters that must be escaped in shell.
|
||||||
pub const special_chars = ' \$"\'\\!'
|
pub const special_chars = ' \$"\'\\!'
|
||||||
|
|
||||||
const special_chars_runes = [` `, `$`, `"`, `'`, `\``, `\\`, `!`]
|
const special_chars_runes = [` `, `$`, `"`, `'`, `\``, `\\`, `!`]!
|
||||||
|
|
||||||
// quote returns a quoted version of string `s`.
|
// quote returns a quoted version of string `s`.
|
||||||
//
|
//
|
||||||
@@ -163,12 +163,14 @@ fn parse(line string) ![]string {
|
|||||||
mut single_quoted := false
|
mut single_quoted := false
|
||||||
mut double_quoted := false
|
mut double_quoted := false
|
||||||
mut back_quoted := false
|
mut back_quoted := false
|
||||||
mut dollar_quoted := false
|
mut dollar_depth := 0
|
||||||
|
mut commented := false
|
||||||
|
|
||||||
mut got := Mode.no
|
mut got := Mode.no
|
||||||
|
|
||||||
for i, c in line {
|
for i, c in line {
|
||||||
mut r := c
|
mut r := c
|
||||||
|
dollar_quoted := dollar_depth > 0
|
||||||
|
|
||||||
if escaped {
|
if escaped {
|
||||||
if r == `t` {
|
if r == `t` {
|
||||||
@@ -177,8 +179,14 @@ fn parse(line string) ![]string {
|
|||||||
if r == `n` {
|
if r == `n` {
|
||||||
r = `\n`
|
r = `\n`
|
||||||
}
|
}
|
||||||
buf << r
|
|
||||||
escaped = false
|
escaped = false
|
||||||
|
if commented {
|
||||||
|
if r == `\n` {
|
||||||
|
commented = false
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
buf << r
|
||||||
got = .normal
|
got = .normal
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -199,6 +207,36 @@ fn parse(line string) ![]string {
|
|||||||
continue
|
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 r.is_space() {
|
||||||
if single_quoted || double_quoted || back_quoted || dollar_quoted {
|
if single_quoted || double_quoted || back_quoted || dollar_quoted {
|
||||||
buf << r
|
buf << r
|
||||||
@@ -217,17 +255,18 @@ fn parse(line string) ![]string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
`(` {
|
`(` {
|
||||||
if !single_quoted && !double_quoted && !dollar_quoted {
|
if !single_quoted && !double_quoted {
|
||||||
if !dollar_quoted && buf.len - 1 >= 0 && buf[buf.len - 1..][0] == `$` {
|
// Opens a `$(` expression or nests inside an already opened one.
|
||||||
dollar_quoted = true
|
if dollar_quoted || (buf.len > 0 && buf.last() == `$`) {
|
||||||
|
dollar_depth++
|
||||||
buf << r
|
buf << r
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`)` {
|
`)` {
|
||||||
if !single_quoted && !double_quoted && !dollar_quoted {
|
if !single_quoted && !double_quoted && dollar_quoted {
|
||||||
dollar_quoted = false
|
dollar_depth--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`"` {
|
`"` {
|
||||||
@@ -264,7 +303,7 @@ fn parse(line string) ![]string {
|
|||||||
single_quoted { return error('non-terminated quote in string') }
|
single_quoted { return error('non-terminated quote in string') }
|
||||||
double_quoted { return error('non-terminated double quote in string') }
|
double_quoted { return error('non-terminated double quote in string') }
|
||||||
back_quoted { return error('non-terminated backtick 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 {}
|
else {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-5
@@ -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
|
// 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
|
// vfmt off
|
||||||
const test_data = {
|
const test_data = {
|
||||||
'foo': ['foo']
|
'foo': ['foo']
|
||||||
@@ -90,10 +89,10 @@ const test_data = {
|
|||||||
'":-) ;-)"': [':-) ;-)']
|
'":-) ;-)"': [':-) ;-)']
|
||||||
'foo `bar baz`': ['foo', '`bar baz`']
|
'foo `bar baz`': ['foo', '`bar baz`']
|
||||||
r'foo "$(bar baz)"': ['foo', r'$(bar baz)']
|
r'foo "$(bar baz)"': ['foo', r'$(bar baz)']
|
||||||
// r'foo $(bar)': ['foo', r'$(bar)'] // failing
|
r'foo $(bar)': ['foo', r'$(bar)']
|
||||||
// r'foo $(bar baz)': ['foo', r'$(bar baz)'] // failing
|
r'foo $(bar baz)': ['foo', r'$(bar baz)']
|
||||||
// r'foo#bar\nbaz': ['foo', 'baz'] // failing
|
r'foo#bar\nbaz': ['foo', 'baz']
|
||||||
// 'foo;bar': ['foo', ';', 'bar'] // failing
|
'foo;bar': ['foo', ';', 'bar']
|
||||||
|
|
||||||
'"foo\\\\\\x bar\\" df\'a\\ \'df"': ['foo\\\\x bar" df\'a\\ \'df']
|
'"foo\\\\\\x bar\\" df\'a\\ \'df"': ['foo\\\\x bar" df\'a\\ \'df']
|
||||||
'"foo\\ x\\x\\\\"\\\'"foobar"': [r"foo\ x\x\'foobar"]
|
'"foo\\ x\\x\\\\"\\\'"foobar"': [r"foo\ x\x\'foobar"]
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
Module {
|
Module {
|
||||||
name: 'shellish'
|
name: 'shellish'
|
||||||
description: 'Shell-like syntax parser and text processor'
|
description: 'Shell-like syntax parser and text processor'
|
||||||
version: '0.1.0'
|
version: '0.1.1'
|
||||||
license: 'MIT'
|
license: 'MIT'
|
||||||
dependencies: []
|
dependencies: []
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user