Files
org-vim/runtime/syntax/testdir/input/sh_mksh.ksh
Johnothan King 56033b9df3 runtime(sh): Fix some ksh-specific deficiencies in syntax script
- Amend syntax highlighting to allow for ksh93 discipline function names
  (e.g. 'foo.get()') and mksh's odd function naming idiosyncrasies
  (shNamespaceOne was introduced to enforce stricter naming rules for
  ksh93 namespaces).
- Remove 'bind' from ksh93 syntax (such a builtin has never been
  implemented in ksh93).
- 'xgrep' is only available in ksh93v- as an alternative way to
  invoke the builtin 'grep -X', so reflect that in the syntax
  highlighting.
- Forbid bash-style 'function name() {' syntax when highlighting
  ksh88 and ksh93 scripts.
- Fix bug causing ' ()' to be incorrectly validated in mksh scripts.
- Add the many ksh93/ksh2020 .sh.* variables to the list of special
  variables.
- Amend iskeyword to allow '.' so that '.sh.tilde.get' and such are
  valid function names/variable names. (For mksh functions starting
  with odd characters like '%' and '@' this would probably have too
  many bad side effects, so I've omitted such a change for that shell.)
- Add new syntax tests and regenerate syntax dump files

closes: #19383

Signed-off-by: Johnothan King <johnothanking@protonmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
2026-02-12 18:18:44 +01:00

207 lines
5.1 KiB
Bash

#!/bin/mksh
# Rendering namespace variables
echo ${.foo.bar[adsf]} ${foo.bar[1][2]} ${foo.bar[1][az]} ${.foo.bar[1][2]}
echo ${.foo[var]} ${.foo.bar[1]} ${.foo.bar[*]} ${foo.bar##baz} ${.foo.bar##baz}
echo ${.foo.bar[3]##baz} ${.foo.bar[z]##baz} ${sh.version/V/b} ${.sh.version/V/b}
echo ${foo/%bar/foo} ${foo/#bar/foo} ${foo.bar/%bar/foo} ${foo.bar[d]/#bar/foo}
echo ${.foo/%barfoo} ${.foo.bar/#bar/foo} ${.bar.foo/%bar/foo} ${.bar/#bar/foo}
echo ${foo/%barfoo} ${foo/bar/foo} ${barfoo//bar/foo} ${bar/#bar/foo}
echo ${.sh.version^^} ${.sh.version,,} ${KSH_VERSION^} ${KSH_VERSION,}
# 'alarm' builtin (present in ksh93u+, ksh93v- and the 93u+m dev branch).
alarm --man
# The fds and pids builtins. These ksh93 builtins have existed since 2005-05-22
# and 2008-06-02, respectively. However, these were not readily enabled; in
# 93u+m these can be enabled with the builtin command if libcmd.so is present,
# either via 'builtin -f' or (in more recent commits) with a regular invocation
# of the 'builtin' built-in.
# cf. https://github.com/ksh93/ksh/commit/f15e2c41
builtin fds pids
fds; pids
# Unix commands which are provided by ksh as builtins via libcmd.so
basename
cat
chgrp
chmod
chown
cksum
cmp
comm
cp
cut
date
dirname
egrep # Obsolescent
expr
fgrep # Obsolescent
fmt
fold
getconf
grep
head
iconv # 93v-
id
join
ln
logname
ls # 93v-
md5sum
mkdir
mkfifo
mktemp
mv
od # 93v-
paste
pathchk
readlink # 93v-
realpath # 93v-
rev
rm
rmdir
sha1sum # 93v-
sha256sum # 93v-
sha2sum # 93v-
sha384sum # 93v-
sha512sum # 93v-
stty
sum
sync
tail
tee
tr # 93v-
tty
uname
uniq
vmstate # Obsolescent; only available in 93v- and older
wc
xargs # 93v-
xgrep # Obsolescent; only 93v- allows invoking 'grep -X' as 'xgrep'
# SHA command not provided as a builtin but included here for completeness
sha224sum
# poll builtin (93v-)
poll --man
# mkservice and eloop (rarely provided; requires SHOPT_MKSERVICE)
mkservice --man; eloop --help
# some mksh builtins, rename should be highlighted as an external command
bind; rename
# ;& and ;;& in case statements
case x in
bar) false ${baz:1} ;&
foo) true ${foo:0:0} ;;&
*) print ${$bar} ;; # 93v-
esac
# Below is subshare syntax supported by both ksh93 and mksh.
print ${ echo one }
print ${ echo two
}
print ${
echo three }
print ${ echo 'four'; }
print ${ echo 'five' ;}
print ${ echo 'six'
}
print ${ echo 'seven' }
echo ${ print 'eight' }
typeset nine=${ pwd; }
# Value substitutions of the form ${|command} are only
# supported by mksh, not ksh93.
if ! command eval '((.sh.version >= 20070703))' 2>/dev/null; then
valsubfunc() {
REPLY=$1
}
echo ${|valsubfunc ten}
print "${|valsubfunc eleven;}"
printf '%s' "${|valsubfunc twelve }"
unlucky=${|valsubfunc thirteen
}
typeset notafloat=${|valsubfunc notanumber }
print $unlucky $notanumber
${|echo foo}
${|echo bar
}
fi
# ======
# Shared-state command substitutions using the syntax ${<file;}
# are only supported by ksh93, not mksh.
echo ${
printf %s str
} > /tmp/strfile
echo ${</tmp/strfile;}
# ksh88 and ksh93 non-dot special variables
print ${ RANDOM= SRANDOM= SHLVL= JOBMAX= KSH_VERSION= FIGNORE= LC_TIME= LC_NUMERIC= LC_MESSAGES= LC_CTYPE= LC_COLLATE= LC_ALL= LANG= FPATH= PS4= OPTIND= OPTARG= true ;}
print $(LINENO= SECONDS= TMOUT= PPID= LINES= COLUMNS= VISUAL= OLDPWD= PS3= MAILPATH= CDPATH= FCEDIT= HISTCMD= HISTEDIT= HISTSIZE= HISTFILE= ENV= MAILCHECK= EDITOR= SHELL= false)
print $(REPLY= MAIL= HOME= PWD= IFS= PS2= PS1= PATH= SH_OPTIONS= ERRNO= COMP_CWORD= COMP_LINE= COMP_POINT= COMP_WORDS= COMP_KEY= COMPREPLY= COMP_WORDBREAKS= COMP_TYPE= compgen)
print $(BASHPID= EPOCHREALTIME= EXECSHELL= KSHEGID= KSHGID= KSHUID= KSH_MATCH= PATHSEP= PGRP= PIPESTATUS= TMPDIR= USER_ID= VPATH= CSWIDTH= complete)
# ksh93 namespace (dot) special variables
print $(.sh= .sh.edchar= .sh.edcol= .sh.edtext= .sh.edmode= .sh.name= .sh.subscript= .sh.value= .sh.version= .sh.match= .sh.command= .sh.file= .sh.fun= .sh.subshell= .sh.level= .sh.lineno= .sh.stats= .sh.math= .sh.pid= .sh.ppid= .sh.tilde= .sh.dollar= .sh.pool= .sh.pgrp= .sh.pwdfd= .sh.op_astbin= .sh.sig= .sh.sig.addr= .sh.sig.band= .sh.sig.code= .sh.sig.errno= .sh.sig.name= .sh.sig.pid= .sh.sig.signo= .sh.sig.status= .sh.sig.uid= .sh.sig.value= .sh.sig.value.q= .sh.sig.value.Q= .sh.stats= .sh.stats.arg_cachehits= .sh.stats.arg_expands= .sh.stats.comsubs= .sh.stats.forks= .sh.stats.funcalls= .sh.stats.globs= .sh.stats.linesread= .sh.stats.nv_cachehit= .sh.stats.nv_opens= .sh.stats.pathsearch= .sh.stats.posixfuncall= .sh.stats.simplecmds= .sh.stats.spawns= .sh.stats.subshell= .sh.install_prefix= complete)
.sh.tilde.get() {
true
}
function .sh.tilde.set {
false
}
function foo() {
: # Bash-style function (mksh-only)
}
function foo2 {
: # KornShell-style function
}
foo3() {
: # POSIX function
}
foo4.get() {
: # POSIX-style ksh93 discipline function
}
function foo5.set {
: # KornShell-style ksh93 discipline function
}
_foo6.unset() (
: # POSIX-style subshell discipline function
)
namespace _foo {
:
}
namespace 1bad.invalid {
:
}
namespace foo1() {
: # Bad syntax
}
# Bad syntax (no name)
function {
false
}
# Bad syntax also
() {
false
}
()
{
false
}