//: Clean syntax to manipulate and check the console in scenarios. //: Instruction 'assume-console' implicitly creates a variable called //: 'console' that is accessible inside other 'run' instructions in the //: scenario. Like with the fake screen, 'assume-console' transparently //: supports unicode. :(scenarios run_mu_scenario) :(scenario keyboard_in_scenario) scenario keyboard-in-scenario [ assume-console [ type [abc] ] run [ 1:character, console:address, 2:boolean <- read-key console:address 3:character, console:address, 4:boolean <- read-key console:address 5:character, console:address, 6:boolean <- read-key console:address 7:character, console:address, 8:boolean, 9:boolean <- read-key console:address ] memory-should-contain [ 1 <- 97 # 'a' 2 <- 1 3 <- 98 # 'b' 4 <- 1 5 <- 99 # 'c' 6 <- 1 7 <- 0 # unset 8 <- 1 9 <- 1 # end of test events ] ] :(before "End Scenario Globals") const long long int CONSOLE = Next_predefined_global_for_scenarios++; :(before "End Special Scenario Variable Names(r)") Name[r]["console"] = CONSOLE; //: allow naming just for 'console' :(before "End is_special_name Cases") if (s == "console") return true; //: Unlike assume-keyboard, assume-console is easiest to implement as just a //: primitive recipe. :(before "End Primitive Recipe Declarations") ASSUME_CONSOLE, :(before "End Primitive Recipe Numbers") Recipe_ordinal["assume-console"] = ASSUME_CONSOLE; :(before "End Primitive Recipe Implementations") case ASSUME_CONSOLE: { // create a temporary recipe just for parsing; it won't contain valid instructions istringstream in("[" + current_instruction().ingredients.at(0).name + "]"); recipe r = slurp_body(in); long long int num_events = count_events(r); // initialize the events long long int size = num_events*size_of_event() + /*space for length*/1; ensure_space(size); long long int event_data_address = Current_routine->alloc; Memory[event_data_address] = num_events; ++Current_routine->alloc; for (long long int i = 0; i < SIZE(r.steps); ++i) { const instruction& curr = r.steps.at(i); if (curr.name == "left-click") { Memory[Current_routine->alloc] = /*tag for 'touch-event' variant of 'event' exclusive-container*/2; Memory[Current_routine->alloc+1+/*offset of 'type' in 'mouse-event'*/0] = TB_KEY_MOUSE_LEFT; Memory[Current_routine->alloc+1+/*offset of 'row' in 'mouse-event'*/1] = to_integer(curr.ingredients.at(0).name); Memory[Current_routine->alloc+1+/*offset of 'column' in 'mouse-event'*/2] = to_integer(curr.ingredients.at(1).name); Current_routine->alloc += size_of_event(); } else if (curr.name == "press") { string key = curr.ingredients.at(0).name; if (is_integer(key)) Memory[Current_routine->alloc+1] = to_integer(key); else if (Key.find(key) != Key.end()) Memory[Current_routine->alloc+1] = Key[key]; else raise << "assume-console: can't press " << key << '\n' << end(); if (Memory[Current_routine->alloc+1] < 256) // these keys are in ascii Memory[Current_routine->alloc] = /*tag for 'text' variant of 'event' exclusive-container*/0; else { // distinguish from unicode Memory[Current_routine->alloc] = /*tag for 'keycode' variant of 'event' exclusive-container*/1; } Current_routine->alloc += size_of_event(); } // End Event Handlers else { // keyboard input assert(curr.name == "type"); const string& contents = curr.ingredients.at(0).name; const char* raw_contents = contents.c_str(); long long int num_keyboard_events = unicode_length(contents); long long int curr = 0; for (long long int i = 0; i < num_keyboard_events; ++i) { Memory[Current_routine->alloc] = /*tag for 'text' variant of 'event' exclusive-container*/0; uint32_t curr_character; assert(curr < SIZE(contents)); tb_utf8_char_to_unicode(&curr_character, &raw_contents[curr]); Memory[Current_routine->alloc+/*skip<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <title>Mu - subx/038---literal_strings.cc</title> <meta name="Generator" content="Vim/8.0"> <meta name="plugin-version" content="vim7.4_v2"> <meta name="syntax" content="cpp"> <meta name="settings" content="number_lines,use_css,pre_wrap,no_foldcolumn,expand_tabs,line_ids,prevent_copy="> <meta name="colorscheme" content="minimal-light"> <style type="text/css"> <!-- pre { white-space: pre-wrap; font-family: monospace; color: #000000; background-color: #c6c6c6; } body { font-size:12pt; font-family: monospace; color: #000000; background-color: #c6c6c6; } a { color:inherit; } * { font-size:12pt; font-size: 1em; } .cSpecial { color: #008000; } .LineNr { } .traceAbsent { color: #c00000; } .Constant { color: #008787; } .Delimiter { color: #c000c0; } .Special { color: #d70000; } .Identifier { color: #af5f00; } .Normal { color: #000000; background-color: #c6c6c6; padding-bottom: 1px; } .Comment { color: #005faf; } .traceContains { color: #005f00; } --> </style> <script type='text/javascript'> <!-- /* function to open any folds containing a jumped-to line before jumping to it */ function JumpToLine() { var lineNum; lineNum = window.location.hash; lineNum = lineNum.substr(1); /* strip off '#' */ if (lineNum.indexOf('L') == -1) { lineNum = 'L'+lineNum; } lineElem = document.getElementById(lineNum); /* Always jump to new location even if the line was hidden inside a fold, or * we corrected the raw number to a line ID. */ if (lineElem) { lineElem.scrollIntoView(true); } return true; } if ('onhashchange' in window) { window.onhashchange = JumpToLine; } --> </script> </head> <body onload='JumpToLine();'> <a href='https://github.com/akkartik/mu/blob/master/subx/038---literal_strings.cc'>https://github.com/akkartik/mu/blob/master/subx/038---literal_strings.cc</a> <pre id='vimCodeElement'> <span id="L1" class="LineNr"> 1 </