public List<Variable> getVariables(String command) {
    String[] cmds = command.split(" ");
    List<String> args = new ArrayList(Arrays.asList(cmds));

    StringBuilder lastVar = new StringBuilder();

    ArrayList<Variable> vars = new ArrayList<Variable>();
    Variable v = null;
    for (int j = 0; j < cleft.size(); j++) {
      try {
        if (cleft.get(j).getCType() == ConstructType.VARIABLE) {
          if (((Variable) cleft.get(j)).getName().equals("$")) {
            for (int k = j; k < args.size(); k++) {
              lastVar.append(args.get(k).trim()).append(" ");
            }
            v =
                new Variable(
                    ((Variable) cleft.get(j)).getName(), lastVar.toString().trim(), Target.UNKNOWN);
          } else {
            v = new Variable(((Variable) cleft.get(j)).getName(), args.get(j), Target.UNKNOWN);
          }
        }
      } catch (IndexOutOfBoundsException e) {
        v =
            new Variable(
                ((Variable) cleft.get(j)).getName(),
                ((Variable) cleft.get(j)).getDefault(),
                Target.UNKNOWN);
      }
      if (v != null) {
        vars.add(v);
      }
    }
    return vars;
  }
  public boolean match(String command) {
    if (cleft == null) {
      // The compilation error happened during the signature declaration, so
      // we can't match it, nor can we even tell if it's what they intended for us to run.
      return false;
    }
    boolean case_sensitive = Prefs.CaseSensitive();
    String[] cmds = command.split(" ");
    List<String> args = new ArrayList(Arrays.asList(cmds));
    boolean isAMatch = true;
    StringBuilder lastVar = new StringBuilder();
    int lastJ = 0;
    try {
      for (int j = 0; j < cleft.size(); j++) {
        if (!isAMatch) {
          break;
        }
        lastJ = j;
        Construct c = cleft.get(j);
        String arg = args.get(j);
        if (c.getCType() != ConstructType.VARIABLE) {
          if (case_sensitive && !c.val().equals(arg)
              || !case_sensitive && !c.val().equalsIgnoreCase(arg)) {
            isAMatch = false;
            continue;
          }
        } else {
          // It's a variable. If it's optional, the rest of them are optional too, so as long as the
          // size of
          // args isn't greater than the size of cleft, it's a match
          if (((Variable) c).isOptional()) {
            if (args.size() <= cleft.size()) {
              return true;
            } else {
              Construct fin = cleft.get(cleft.size() - 1);
              if (fin instanceof Variable) {
                if (((Variable) fin).isFinal()) {
                  return true;
                }
              }
              return false;
            }
          }
        }
        if (j == cleft.size() - 1) {
          if (cleft.get(j).getCType() == ConstructType.VARIABLE) {
            Variable lv = (Variable) cleft.get(j);
            if (lv.isFinal()) {
              for (int a = j; a < args.size(); a++) {
                if (lastVar.length() == 0) {
                  lastVar.append(args.get(a));
                } else {
                  lastVar.append(" ").append(args.get(a));
                }
              }
            }
          }
        }
      }
    } catch (IndexOutOfBoundsException e) {
      if (cleft.get(lastJ).getCType() != ConstructType.VARIABLE
          || cleft.get(lastJ).getCType() == ConstructType.VARIABLE
              && !((Variable) cleft.get(lastJ)).isOptional()) {
        isAMatch = false;
      }
    }
    boolean lastIsFinal = false;
    if (cleft.get(cleft.size() - 1) instanceof Variable) {
      Variable v = (Variable) cleft.get(cleft.size() - 1);
      if (v.isFinal()) {
        lastIsFinal = true;
      }
    }
    if ((cleft.get(lastJ) instanceof Variable && ((Variable) cleft.get(lastJ)).isOptional())) {
      return true;
    }

    if (cleft.size() != cmds.length && !lastIsFinal) {
      isAMatch = false;
    }
    //        ArrayList<Variable> vars = new ArrayList<Variable>();
    //        Variable v = null;
    //        for (int j = 0; j < cleft.size(); j++) {
    //            try {
    //                if (cleft.get(j).getCType() == ConstructType.VARIABLE) {
    //                    if (((Variable) cleft.get(j)).getName().equals("$")) {
    //                        v = new Variable(((Variable) cleft.get(j)).getName(),
    //                                lastVar.toString(), Target.UNKNOWN);
    //                    } else {
    //                        v = new Variable(((Variable) cleft.get(j)).getName(),
    //                                args.get(j), Target.UNKNOWN);
    //                    }
    //                }
    //            } catch (IndexOutOfBoundsException e) {
    //                v = new Variable(((Variable) cleft.get(j)).getName(),
    //                        ((Variable) cleft.get(j)).getDefault(), Target.UNKNOWN);
    //            }
    //            if (v != null) {
    //                vars.add(v);
    //            }
    //        }
    return isAMatch;
  }