Skip to content

Commit

Permalink
Merge branch 'soil-staging' into detect-glob-period
Browse files Browse the repository at this point in the history
  • Loading branch information
Andy C committed Jan 5, 2025
2 parents fcdc2a0 + 3b861d6 commit 1d8b69d
Show file tree
Hide file tree
Showing 42 changed files with 1,673 additions and 321 deletions.
4 changes: 3 additions & 1 deletion builtin/assign_osh.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,9 @@ def Run(self, cmd_val):
if arg.a:
rval = value.BashArray([]) # type: value_t
elif arg.A:
rval = value.BashAssoc({})
# mycpp limitation: NewDict() needs to be typed
tmp = NewDict() # type: Dict[str, str]
rval = value.BashAssoc(tmp)
else:
rval = None
else:
Expand Down
14 changes: 10 additions & 4 deletions builtin/completion_osh.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from _devbuild.gen.syntax_asdl import loc
from _devbuild.gen.value_asdl import (value, value_e)

from core import bash_impl
from core import completion
from core import error
from core import state
Expand Down Expand Up @@ -454,9 +455,13 @@ def Run(self, cmd_val):
# TODO: How does the user test a completion function programmatically? Set
# COMP_ARGV?
val = self.mem.GetValue('COMP_ARGV')
if val.tag() != value_e.BashArray:
if val.tag() == value_e.BashArray:
comp_argv = cast(value.BashArray, val).strs
elif val.tag() == value_e.SparseArray:
comp_argv = bash_impl.SparseArray_GetValues(
cast(value.SparseArray, val))
else:
raise error.Usage("COMP_ARGV should be an array", loc.Missing)
comp_argv = cast(value.BashArray, val).strs

# These are the ones from COMP_WORDBREAKS that we care about. The rest occur
# "outside" of words.
Expand All @@ -476,13 +481,14 @@ def Run(self, cmd_val):
# argv adjusted according to 'break_chars'.
adjusted_argv = [] # type: List[str]
for a in comp_argv:
completion.AdjustArg(a, break_chars, adjusted_argv)
if a is not None:
completion.AdjustArg(a, break_chars, adjusted_argv)

if 'words' in var_names:
state.BuiltinSetArray(self.mem, 'words', adjusted_argv)

n = len(adjusted_argv)
cur = adjusted_argv[-1]
cur = '' if n < 1 else adjusted_argv[-1]
prev = '' if n < 2 else adjusted_argv[-2]

if arg.s:
Expand Down
3 changes: 3 additions & 0 deletions builtin/pure_ysh.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,9 @@ def Run(self, cmd_val):
if case(value_e.BashArray):
val = cast(value.BashArray, UP_val)
bash_impl.BashArray_AppendValues(val, arg_r.Rest())
elif case(value_e.SparseArray):
val = cast(value.SparseArray, UP_val)
bash_impl.SparseArray_AppendValues(val, arg_r.Rest())
elif case(value_e.List):
val = cast(value.List, UP_val)
typed = [value.Str(s)
Expand Down
61 changes: 25 additions & 36 deletions core/bash_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,31 @@

def BigInt_Greater(a, b):
# type: (mops.BigInt, mops.BigInt) -> bool

return mops.Greater(a, b)


def BigInt_Less(a, b):
# type: (mops.BigInt, mops.BigInt) -> bool

return mops.Greater(b, a)


def BigInt_GreaterEq(a, b):
# type: (mops.BigInt, mops.BigInt) -> bool

return not mops.Greater(b, a)


def BigInt_LessEq(a, b):
# type: (mops.BigInt, mops.BigInt) -> bool

return not mops.Greater(a, b)


#------------------------------------------------------------------------------
# All BashArray operations depending on the internal
# representation of SparseArray come here.
# All BashArray operations depending on the internal representation of
# BashArray come here.


def BashArray_IsEmpty(array_val):
# type: (value.BashArray) -> bool

return len(array_val.strs) == 0


Expand All @@ -58,13 +53,11 @@ def BashArray_Count(array_val):

def BashArray_Length(array_val):
# type: (value.BashArray) -> int

return len(array_val.strs)


def BashArray_GetKeys(array_val):
# type: (value.BashArray) -> List[int]

indices = [] # type: List[int]
for i, s in enumerate(array_val.strs):
if s is not None:
Expand All @@ -75,13 +68,11 @@ def BashArray_GetKeys(array_val):

def BashArray_GetValues(array_val):
# type: (value.BashArray) -> List[str]

return array_val.strs


def BashArray_AppendValues(array_val, strs):
# type: (value.BashArray, List[str]) -> None

array_val.strs.extend(strs)


Expand All @@ -104,7 +95,6 @@ def _BashArray_CanonicalizeIndex(array_val, index):

def BashArray_HasElement(array_val, index):
# type: (value.BashArray, int) -> Tuple[bool, error_code_t]

index, n, error_code = _BashArray_CanonicalizeIndex(array_val, index)
if error_code != error_code_e.OK:
return False, error_code
Expand Down Expand Up @@ -140,7 +130,6 @@ def BashArray_GetElement(array_val, index):

def BashArray_SetElement(array_val, index, s):
# type: (value.BashArray, int, str) -> error_code_t

strs = array_val.strs

# a[-1]++ computes this twice; could we avoid it?
Expand Down Expand Up @@ -192,7 +181,6 @@ def BashArray_UnsetElement(array_val, index):

def BashArray_Equals(lhs, rhs):
# type: (value.BashArray, value.BashArray) -> bool

len_lhs = len(lhs.strs)
len_rhs = len(rhs.strs)
if len_lhs != len_rhs:
Expand All @@ -217,7 +205,6 @@ def _BashArray_HasHoles(array_val):

def BashArray_ToStrForShellPrint(array_val, name):
# type: (value.BashArray, Optional[str]) -> str

buff = [] # type: List[str]
first = True
if _BashArray_HasHoles(array_val):
Expand Down Expand Up @@ -266,8 +253,8 @@ def BashArray_ToStrForShellPrint(array_val, name):


#------------------------------------------------------------------------------
# All BashAssoc operations depending on the internal
# representation of SparseArray come here.
# All BashAssoc operations depending on the internal representation of
# BashAssoc come here.


def BashAssoc_IsEmpty(assoc_val):
Expand All @@ -282,56 +269,47 @@ def BashAssoc_Count(assoc_val):

def BashAssoc_GetDict(assoc_val):
# type: (value.BashAssoc) -> Dict[str, str]

return assoc_val.d


def BashAssoc_AppendDict(assoc_val, d):
# type: (value.BashAssoc, Dict[str, str]) -> None

for key in d:
assoc_val.d[key] = d[key]


def BashAssoc_GetKeys(assoc_val):
# type: (value.BashAssoc) -> List[str]

return assoc_val.d.keys()


def BashAssoc_GetValues(assoc_val):
# type: (value.BashAssoc) -> List[str]

return assoc_val.d.values()


def BashAssoc_HasElement(assoc_val, s):
# type: (value.BashAssoc, str) -> bool

return s in assoc_val.d


def BashAssoc_GetElement(assoc_val, s):
# type: (value.BashAssoc, str) -> Optional[str]

return assoc_val.d.get(s)


def BashAssoc_SetElement(assoc_val, key, s):
# type: (value.BashAssoc, str, str) -> None

assoc_val.d[key] = s


def BashAssoc_UnsetElement(assoc_val, key):
# type: (value.BashAssoc, str) -> None

mylib.dict_erase(assoc_val.d, key)


def BashAssoc_Equals(lhs, rhs):
# type: (value.BashAssoc, value.BashAssoc) -> bool

if len(lhs.d) != len(rhs.d):
return False

Expand All @@ -344,7 +322,6 @@ def BashAssoc_Equals(lhs, rhs):

def BashAssoc_ToStrForShellPrint(assoc_val):
# type: (value.BashAssoc) -> str

buff = ["("] # type: List[str]
first = True
for key in sorted(assoc_val.d):
Expand All @@ -363,8 +340,13 @@ def BashAssoc_ToStrForShellPrint(assoc_val):


#------------------------------------------------------------------------------
# All SparseArray operations depending on the internal
# representation of SparseArray come here.
# All SparseArray operations depending on the internal representation of
# SparseArray come here.


def SparseArray_IsEmpty(sparse_val):
# type: (value.SparseArray) -> bool
return len(sparse_val.d) == 0


def SparseArray_Count(sparse_val):
Expand All @@ -374,13 +356,11 @@ def SparseArray_Count(sparse_val):

def SparseArray_Length(sparse_val):
# type: (value.SparseArray) -> mops.BigInt

return mops.Add(sparse_val.max_index, mops.ONE)


def SparseArray_GetKeys(sparse_val):
# type: (value.SparseArray) -> List[mops.BigInt]

keys = sparse_val.d.keys()
mylib.BigIntSort(keys)
return keys
Expand Down Expand Up @@ -426,7 +406,6 @@ def _SparseArray_CanonicalizeIndex(sparse_val, index):

def SparseArray_HasElement(sparse_val, index):
# type: (value.SparseArray, mops.BigInt) -> Tuple[bool, error_code_t]

index, error_code = _SparseArray_CanonicalizeIndex(sparse_val, index)
if error_code != error_code_e.OK:
return False, error_code
Expand All @@ -435,7 +414,6 @@ def SparseArray_HasElement(sparse_val, index):

def SparseArray_GetElement(sparse_val, index):
# type: (value.SparseArray, mops.BigInt) -> Tuple[Optional[str], error_code_t]

index, error_code = _SparseArray_CanonicalizeIndex(sparse_val, index)
if error_code != error_code_e.OK:
return None, error_code
Expand All @@ -444,7 +422,6 @@ def SparseArray_GetElement(sparse_val, index):

def SparseArray_SetElement(sparse_val, index, s):
# type: (value.SparseArray, mops.BigInt, str) -> error_code_t

index, error_code = _SparseArray_CanonicalizeIndex(sparse_val, index)
if error_code != error_code_e.OK:
return error_code
Expand All @@ -456,7 +433,6 @@ def SparseArray_SetElement(sparse_val, index, s):

def SparseArray_UnsetElement(sparse_val, index):
# type: (value.SparseArray, mops.BigInt) -> error_code_t

index, error_code = _SparseArray_CanonicalizeIndex(sparse_val, index)
if error_code != error_code_e.OK:
return error_code
Expand All @@ -471,9 +447,22 @@ def SparseArray_UnsetElement(sparse_val, index):
return error_code_e.OK


def SparseArray_Equals(lhs, rhs):
# type: (value.SparseArray, value.SparseArray) -> bool
len_lhs = len(lhs.d)
len_rhs = len(rhs.d)
if len_lhs != len_rhs:
return False

for index in lhs.d:
if index not in rhs.d or rhs.d[index] != lhs.d[index]:
return False

return True


def SparseArray_ToStrForShellPrint(sparse_val):
# type: (value.SparseArray) -> str

body = [] # type: List[str]
for index in SparseArray_GetKeys(sparse_val):
if len(body) > 0:
Expand Down
44 changes: 28 additions & 16 deletions core/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
from _devbuild.gen.runtime_asdl import (scope_e, comp_action_e, comp_action_t)
from _devbuild.gen.types_asdl import redir_arg_type_e
from _devbuild.gen.value_asdl import (value, value_e)
from core import bash_impl
from core import error
from core import pyos
from core import state
Expand All @@ -51,7 +52,7 @@
from frontend import location
from frontend import reader
from mycpp import mylib
from mycpp.mylib import print_stderr, iteritems, log
from mycpp.mylib import iteritems, log, print_stderr, tagswitch
from osh.string_ops import ShellQuoteB
from osh import word_
from pylib import os_path
Expand Down Expand Up @@ -619,25 +620,36 @@ def Matches(self, comp):
# Read the response. (The name 'COMP_REPLY' would be more consistent with others.)
val = self.cmd_ev.mem.GetValue('COMPREPLY', scope_e.GlobalOnly)

if val.tag() == value_e.Undef:
# We set it above, so this error would only happen if the user unset it.
# Not changing it means there were no completions.
# TODO: This writes over the command line; it would be better to use an
# error object.
print_stderr('osh error: Ran function %r but COMPREPLY was unset' %
self.func.name)
return

if val.tag() != value_e.BashArray:
print_stderr('osh error: COMPREPLY should be an array, got %s' %
ui.ValType(val))
return
UP_val = val
with tagswitch(val) as case:
if case(value_e.Undef):
# We set it above, so this error would only happen if the user
# unset it. Not changing it means there were no completions.
# TODO: This writes over the command line; it would be better
# to use an error object.
print_stderr(
'osh error: Ran function %r but COMPREPLY was unset' %
self.func.name)
return
elif case(value_e.Str):
val = cast(value.Str, UP_val)
strs = [val.s]
elif case(value_e.BashArray):
val = cast(value.BashArray, UP_val)
strs = bash_impl.BashArray_GetValues(val)
elif case(value_e.SparseArray):
val = cast(value.SparseArray, UP_val)
strs = bash_impl.SparseArray_GetValues(val)
else:
print_stderr(
'osh error: COMPREPLY should be an array or a string, got %s'
% ui.ValType(val))
return

if 0:
self.debug('> %r' % val) # CRASHES in C++

array_val = cast(value.BashArray, val)
for s in array_val.strs:
for s in strs:
#self.debug('> %r' % s)
yield s

Expand Down
Loading

0 comments on commit 1d8b69d

Please sign in to comment.