GithubHelp home page GithubHelp logo

Comments (3)

niieani avatar niieani commented on July 27, 2024

Indeed, this is a serious problem.
I've thought about it for a while and come up with a re-written, simpler (but more powerful) way to declare and assign parameters. It comes with a new syntax though (two options, comma separated or new line starting with :), but I'm sure it will be possible to make backwards-compatible aliases.

It looks like this:

# syntax with commas:
function example { args : @required string firstName , string lastName , integer age } {
  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
}

# syntax with colons and new lines:
function example {
  args
    : @required string firstName
    : string lastName
    : integer age
    : string[] ...favoriteHobbies

  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
  echo "My favorite hobbies include: ${favoriteHobbies[*]}"
}

# normal usage:
example Mark McDonald 32 singing jumping

Try playing around with this snippet and feel free to give me your feedback:

#!/usr/bin/env bash

shopt -s expand_aliases

function echo_stderr {
  echo "$*" >&2
}

function assignTrap {
  local evalString
  local -i paramIndex=${__paramIndex-0}
  local initialCommand="${1-}"

  if [[ "$initialCommand" != ":" ]]
  then
    echo "trap - DEBUG; eval \"${__previousTrap}\"; unset __previousTrap; unset __paramIndex;"
    return
  fi

  while [[ "${1-}" == "," || "${1-}" == "${initialCommand}" ]] || [[ "${#@}" -gt 0 && "$paramIndex" -eq 0 ]]
  do
    shift # first colon ":" or next parameter's comma ","
    paramIndex+=1
    local -a decorators=()
    while [[ "${1-}" == "@"* ]]
    do
      decorators+=( "$1" )
      shift
    done

    local declaration=
    local wrapLeft='"'
    local wrapRight='"'
    local nextType="$1"
    local length=1

    case ${nextType} in
      string | boolean) declaration="local " ;;
      integer) declaration="local -i" ;;
      reference) declaration="local -n" ;;
      arrayDeclaration) declaration="local -a"; wrapLeft= ; wrapRight= ;;
      assocDeclaration) declaration="local -A"; wrapLeft= ; wrapRight= ;;
      "string["*"]") declaration="local -a"; length="${nextType//[a-z\[\]]}" ;;
      "integer["*"]") declaration="local -ai"; length="${nextType//[a-z\[\]]}" ;;
    esac

    if [[ "${declaration}" != "" ]]
    then
      shift
      local nextName="$1"
      local handleless=

      for decorator in "${decorators[@]}"
      do
        case ${decorator} in
          @readonly) declaration+="r" ;;
          @required) evalString+="[[ ! -z \$${paramIndex} ]] || echo_stderr \"Parameter '$nextName' ($nextType) is marked as required by '${FUNCNAME[1]}' function.\"; " ;;
          @handleless) handleless=1 ;;
          @global) declaration+="g" ;;
        esac
      done

      local paramRange="$paramIndex"

      if [[ -z "$length" ]]
      then
        # ...rest
        paramRange="{@:$paramIndex}"
        # trim leading ...
        nextName="${nextName//\./}"
        if [[ "${#@}" -gt 1 ]]
        then
          echo_stderr "Unexpected arguments after a rest array ($nextName) in '${FUNCNAME[1]}' function."
        fi
      elif [[ "$length" -gt 1 ]]
      then
        paramRange="{@:$paramIndex:$length}"
        paramIndex+=$((length - 1))
      fi

      evalString+="${declaration} ${nextName}=${wrapLeft}\$${paramRange}${wrapRight}; "

      # if [[ "$handleless" != 1 ]]
      # then
      #   evalString+="Type::CreateHandlerFunction \"$nextName\"; "
      # fi

      # continue to the next param:
      shift
    fi
  done
  # echo_stderr "evaling $evalString"
  echo "${evalString} local -i __paramIndex=${paramIndex};"
}

alias args='local __previousTrap=$(trap -p DEBUG); trap "eval \"\$(assignTrap \$BASH_COMMAND)\";" DEBUG;'

# syntax with commas:
function example { args : @required string firstName , string lastName , integer age } {
  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
}

# syntax with colons and new lines:
function example {
  args
    : @required string firstName
    : string lastName
    : integer age
    : string[] ...favoriteHobbies

  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
  echo "My favorite hobbies include: ${favoriteHobbies[*]}"
}

example Mark McDonald 32 singing jumping

from bash-oo-framework.

nkakouros avatar nkakouros commented on July 27, 2024

alias args='local __previousTrap=$(trap -p DEBUG); trap "eval "$(assignTrap $BASH_COMMAND)";" DEBUG;'

This line missing from the current version had me spending 3 hours of going through thousands of set -x output lines. 😛 .

There is also the issue of the functrace option being set which might break things (it does in the current version and I think it will cause problems here as well when local __previousTrap=$(trap -p DEBUG); gets run a second time, ie when a second argument is being evaluated).

I find this implementation to be awesome! I cannot decide if I like the new syntax more or not. I would still like to explore the possibility of having the old aliases work.

My only objection is the comma syntax. I think it breaks the bash function "signature", ie instead of

[function] func_name[()] {.*}

we now have:

[function] func_name[()] {.*}{.*}

This might break existing tools that rely on the first "signature" to scan the code and identify function definitions, etc.

from bash-oo-framework.

niieani avatar niieani commented on July 27, 2024

Thanks for the feedback!

I think old aliases could be ported - I was thinking how to do it and it shouldn't be too hard to add.

As for the comma signature, it shouldn't break. Here's why: the second } and { are really just arguments passed to the first command (args), formatted on the same line as the opening brace {.

function example {
  args : @required string firstName , string lastName , integer age } {
  echo "My name is ${firstName} ${lastName} and I am ${age} years old."
}

The curly braces really just there as a decoration, as they're ignored by assignTrap.

At least when I've tried with shellcheck, it worked.

No idea about how it might work with functrace -- worth checking. There's probably a way to workaround any problems, too.

from bash-oo-framework.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.