about summary refs log tree commit diff stats
path: root/src/ui
ModeNameSize
-rw-r--r--buffer.c4977log stats plain blame
-rw-r--r--buffer.h2893log stats plain blame
-rw-r--r--chatwin.c16102log stats plain blame
-rw-r--r--confwin.c12769log stats plain blame
-rw-r--r--console.c87372log stats plain blame
-rw-r--r--core.c36141log stats plain blame
-rw-r--r--inputwin.c21240log stats plain blame
-rw-r--r--inputwin.h1797log stats plain blame
-rw-r--r--mucwin.c31004log stats plain blame
-rw-r--r--notifier.c9010log stats plain blame
-rw-r--r--occupantswin.c7918log stats plain blame
-rw-r--r--privwin.c8219log stats plain blame
-rw-r--r--rosterwin.c46654log stats plain blame
-rw-r--r--screen.c3310log stats plain blame
-rw-r--r--screen.h1700log stats plain blame
-rw-r--r--statusbar.c17451log stats plain blame
-rw-r--r--statusbar.h1923log stats plain blame
-rw-r--r--titlebar.c15485logpre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
//: Phase 1 of running mu code: load it from a textual representation.

:(scenarios load)  // use 'load' instead of 'run' in all scenarios in this layer
:(scenario first_recipe)
recipe main [
  1:number <- copy 23:literal
]
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal"]}
+parse:   product: {name: "1", properties: ["1": "number"]}

:(code)
vector<recipe_ordinal> load(string form) {
  istringstream in(form);
  in >> std::noskipws;
  return load(in);
}

vector<recipe_ordinal> load(istream& in) {
  in >> std::noskipws;
  vector<recipe_ordinal> result;
  while (!in.eof()) {
//?     cerr << "===\n"; //? 1
    skip_whitespace_and_comments(in);
    if (in.eof()) break;
    string command = next_word(in);
    // Command Handlers
    if (command == "recipe") {
      string recipe_name = next_word(in);
//?       cerr << "recipe: " << recipe_name << '\n'; //? 1
      if (recipe_name.empty())
        raise << "empty recipe name\n" << end();
      if (Recipe_ordinal.find(recipe_name) == Recipe_ordinal.end()) {
        Recipe_ordinal[recipe_name] = Next_recipe_ordinal++;
      }
      if (warn_on_redefine(recipe_name)
          && Recipe.find(Recipe_ordinal[recipe_name]) != Recipe.end()) {
        raise << "redefining recipe " << Recipe[Recipe_ordinal[recipe_name]].name << "\n" << end();
      }
      // todo: save user-defined recipes to mu's memory
      Recipe[Recipe_ordinal[recipe_name]] = slurp_recipe(in);
//?       cerr << Recipe_ordinal[recipe_name] << ": " << recipe_name << '\n'; //? 1
      Recipe[Recipe_ordinal[recipe_name]].name = recipe_name;
      // track added recipes because we may need to undo them in tests; see below
      recently_added_recipes.push_back(Recipe_ordinal[recipe_name]);
      result.push_back(Recipe_ordinal[recipe_name]);
    }
    // End Command Handlers
    else {
      raise << "unknown top-level command: " << command << '\n' << end();
    }
  }
  // End Load Sanity Checks
  return result;
}

recipe slurp_recipe(istream& in) {
  recipe result;
  skip_whitespace(in);
  if (in.get() != '[')
    raise << "recipe body must begin with '['\n" << end();
  skip_whitespace_and_comments(in);
  instruction curr;
  while (next_instruction(in, &curr)) {
    // End Rewrite Instruction(curr)
//?     cerr << "instruction: " << curr.to_string() << '\n'; //? 2
    result.steps.push_back(curr);
  }
  return result;
}

bool next_instruction(istream& in, instruction* curr) {
  in >> std::noskipws;
  curr->clear();
  if (in.eof()) return false;
//?   show_rest_of_stream(in); //? 1
  skip_whitespace(in);  if (in.eof()) return false;
//?   show_rest_of_stream(in); //? 1
  skip_whitespace_and_comments(in);  if (in.eof()) return false;

  vector<string> words;
//?   show_rest_of_stream(in); //? 1
  while (in.peek() != '\n') {
    skip_whitespace(in);  if (in.eof()) return false;
//?     show_rest_of_stream(in); //? 1
    string word = next_word(in);  if (in.eof()) return false;
//?     cerr << "AAA: " << word << '\n'; //? 1
    words.push_back(word);
    skip_whitespace(in);  if (in.eof()) return false;
  }
  skip_whitespace_and_comments(in);  if (in.eof()) return false;

//?   if (SIZE(words) == 1) cout << words.at(0) << ' ' << SIZE(words.at(0)) << '\n'; //? 1
  if (SIZE(words) == 1 && words.at(0) == "]") {
//?     cout << "AAA\n"; //? 1
    return false;  // end of recipe
  }

  if (SIZE(words) == 1 && !isalnum(words.at(0).at(0)) && words.at(0).at(0) != '$') {
    curr->is_label = true;
    curr->label = words.at(0);
    trace("parse") << "label: " << curr->label << end();
    return !in.eof();
  }

  vector<string>::iterator p = words.begin();
  if (find(words.begin(), words.end(), "<-") != words.end()) {
    for (; *p != "<-"; ++p) {
      if (*p == ",") continue;
      curr->products.push_back(reagent(*p));
//?       cerr << "product: " << curr->products.back().to_string() << '\n'; //? 1
    }
    ++p;  // skip <-
  }

  if (p == words.end()) {
    raise << "instruction prematurely ended with '<-'\n" << end() << end();
    return false;
  }
  curr->name = *p;
  if (Recipe_ordinal.find(*p) == Recipe_ordinal.end()) {
    Recipe_ordinal[*p] = Next_recipe_ordinal++;
//?     cout << "AAA: " << *p << " is now " << Recipe_ordinal[*p] << '\n'; //? 1
  }
  if (Recipe_ordinal[*p] == 0) {
    raise << "Recipe " << *p << " has number 0, which is reserved for IDLE.\n" << end() << end();
    return false;
  }
  curr->operation = Recipe_ordinal[*p];  ++p;

  for (; p != words.end(); ++p) {
    if (*p == ",") continue;
    curr->ingredients.push_back(reagent(*p));
//?     cerr << "ingredient: " << curr->ingredients.back().to_string() << '\n'; //? 1
  }

  trace("parse") << "instruction: " << curr->name << end();
  for (vector<reagent>::iterator p = curr->ingredients.begin(); p != curr->ingredients.end(); ++p) {
    trace("parse") << "  ingredient: " << p->to_string() << end();
  }
  for (vector<reagent>::iterator p = curr->products.begin(); p != curr->products.end(); ++p) {
    trace("parse") << "  product: " << p->to_string() << end();
  }
  return !in.eof();
}

string next_word(istream& in) {
//?   cout << "AAA next_word\n"; //? 1
  ostringstream out;
  skip_whitespace(in);
  slurp_word(in, out);
  skip_whitespace(in);
  skip_comment(in);
//?   cerr << '^' << out.str() << "$\n"; //? 1
  return out.str();
}

void slurp_word(istream& in, ostream& out) {
//?   cout << "AAA slurp_word\n"; //? 1
  char c;
  if (in.peek() == ',') {
    in >> c;
    out << c;
    return;
  }
  while (in >> c) {
//?     cout << c << '\n'; //? 1
    if (isspace(c) || c == ',') {
      in.putback(c);
      break;
    }
    out << c;
  }
}

void skip_whitespace(istream& in) {
  while (isspace(in.peek()) && in.peek() != '\n') {
    in.get();
  }
}

void skip_whitespace_and_comments(istream& in) {
  while (true) {
    if (isspace(in.peek())) in.get();
    else if (in.peek() == '#') skip_comment(in);
    else break;
  }
}

void skip_comment(istream& in) {
  if (in.peek() == '#') {
    in.get();
    while (in.peek() != '\n') in.get();
  }
}

void skip_comma(istream& in) {
  skip_whitespace(in);
  if (in.peek() == ',') in.get();
  skip_whitespace(in);
}

//: Warn if a recipe gets redefined, because large codebases can accidentally
//: step on their own toes. But there'll be many occasions later where
//: we'll want to disable the warnings.
:(before "End Globals")
bool Disable_redefine_warnings = false;
:(before "End Setup")
Disable_redefine_warnings = false;
:(code)
bool warn_on_redefine(const string& recipe_name) {
  if (Disable_redefine_warnings) return false;
  return true;
}

// for debugging
:(before "End Globals")
bool Show_rest_of_stream = false;
:(code)
void show_rest_of_stream(istream& in) {
  if (!Show_rest_of_stream) return;
  cerr << '^';
  char c;
  while (in >> c) {
    cerr << c;
  }
  cerr << "$\n";
  exit(0);
}

//: Have tests clean up any recipes they added.
:(before "End Globals")
vector<recipe_ordinal> recently_added_recipes;
:(before "End Setup")
for (long long int i = 0; i < SIZE(recently_added_recipes); ++i) {
//?   cout << "AAA clearing " << Recipe[recently_added_recipes.at(i)].name << '\n'; //? 2
  Recipe_ordinal.erase(Recipe[recently_added_recipes.at(i)].name);
  Recipe.erase(recently_added_recipes.at(i));
}
// Clear Other State For recently_added_recipes
recently_added_recipes.clear();

:(scenario parse_comment_outside_recipe)
# this comment will be dropped by the tangler, so we need a dummy recipe to stop that
recipe f1 [ ]
# this comment will go through to 'load'
recipe main [
  1:number <- copy 23:literal
]
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal"]}
+parse:   product: {name: "1", properties: ["1": "number"]}

:(scenario parse_comment_amongst_instruction)
recipe main [
  # comment
  1:number <- copy 23:literal
]
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal"]}
+parse:   product: {name: "1", properties: ["1": "number"]}

:(scenario parse_comment_amongst_instruction2)
recipe main [
  # comment
  1:number <- copy 23:literal
  # comment
]
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal"]}
+parse:   product: {name: "1", properties: ["1": "number"]}

:(scenario parse_comment_amongst_instruction3)
recipe main [
  1:number <- copy 23:literal
  # comment
  2:number <- copy 23:literal
]
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal"]}
+parse:   product: {name: "1", properties: ["1": "number"]}
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal"]}
+parse:   product: {name: "2", properties: ["2": "number"]}

:(scenario parse_comment_after_instruction)
recipe main [
  1:number <- copy 23:literal  # comment
]
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal"]}
+parse:   product: {name: "1", properties: ["1": "number"]}

:(scenario parse_label)
recipe main [
  +foo
]
+parse: label: +foo

:(scenario parse_dollar_as_recipe_name)
recipe main [
  $foo
]
+parse: instruction: $foo

:(scenario parse_multiple_properties)
recipe main [
  1:number <- copy 23:literal/foo:bar:baz
]
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal", "foo": "bar":"baz"]}
+parse:   product: {name: "1", properties: ["1": "number"]}

:(scenario parse_multiple_products)
recipe main [
  1:number, 2:number <- copy 23:literal
]
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal"]}
+parse:   product: {name: "1", properties: ["1": "number"]}
+parse:   product: {name: "2", properties: ["2": "number"]}

:(scenario parse_multiple_ingredients)
recipe main [
  1:number, 2:number <- copy 23:literal, 4:number
]
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal"]}
+parse:   ingredient: {name: "4", properties: ["4": "number"]}
+parse:   product: {name: "1", properties: ["1": "number"]}
+parse:   product: {name: "2", properties: ["2": "number"]}

:(scenario parse_multiple_types)
recipe main [
  1:number, 2:address:number <- copy 23:literal, 4:number
]
+parse: instruction: copy
+parse:   ingredient: {name: "23", properties: ["23": "literal"]}
+parse:   ingredient: {name: "4", properties: ["4": "number"]}
+parse:   product: {name: "1", properties: ["1": "number"]}
+parse:   product: {name: "2", properties: ["2": "address":"number"]}

:(scenario parse_properties)
recipe main [
  1:number:address/deref <- copy 23:literal
]
+parse:   product: {name: "1", properties: ["1": "number":"address", "deref": ]}