Interactive Parsing

version 3 by Jon Ingold

  • Home page
  • Beginning
  • Previous
  • Next



  • Section 2 - Read in the input line using keystrokes

    Include (-

    Global prompted_word = 0;

    Constant PENDING = 1;
    Constant PROCESSING = 2;
    Constant PERFORMED = 3;

    Global current_analysis_stage = PENDING;

    Constant TIME_SKIP = 1;
    Constant MAX_TESTS = 50;

    Global interrupt_keypress = 0;

    Global cursor_position = 0;

    [ New_Key_Input
        a_buffer a_table
        key
        terminated
        rv
        character_press_engaged
        ;

    InitialiseCommandRecall();

        ! set up the line : initialise variables

        terminated = false;
        cursor_position = 0;
        a_buffer-->0 = 0;

        
        ! set up the window: clear prompts and suggestions
        
        glk_cancel_char_event((+key-window+).ref_number);

        ! build some quick look-up tables of verbs, in-scope nouns and prepositions, and the compass
        ! The compass list could be built once at the start of the game, but it's fast, and done here
        ! in case the game changes the names of directions at any point.

        WorkThroughScope(location, word_in_scope_list, MAX_WORD_IN_SCOPE, EX_PREPOSITION, 0, "visible scoped nouns", "maximum words in scope");
        
        WorkThroughScope(Compass, word_for_verb_list, MAX_VERB_NAMES, EX_VERB, animate, "verb words", "maximum verb words");
        
        WorkThroughScope(Compass, word_in_compass_list, MAX_COMPASS_NAMES, EX_NONE, 0, "compass names", "maximum compass names");

        ErasePreviousSuggestions();
        ResetRunningChecks();



        cursor_position = ApplyEditPoint(a_buffer);
        if (cursor_position == 0)
        {
            ClearPromptWindow();
            PrintPromptInWindow();
        }

        ! set up - request a character event

        glk_request_char_event((+key-window+).ref_number);

        ! begin outer loop - reading in the line
        while(~~terminated)
        {
            ! inner loop - wait for something to happen
            while(true)
            {
                ! if we're here from a keypress event that occurred during processing.
                ! We "fake" keypress input

                if (interrupt_keypress ~= 0)
                {
                    ! write in a keypress event
                    gg_event-->0 = evtype_CharInput;
                    gg_event-->2 = interrupt_keypress;
                    interrupt_keypress = 0;
                    character_press_engaged = true;

                }
                else
                {
                    ! Otherwise, stop and wait for an event
                    CorrectlyPositionCursor();
                    glk_select(gg_event);
                }

                ! Event 1 - The Timer has pinged.
                ! Let's go off and do some more analysis

                if (gg_event-->0 == evtype_Timer)
                {
                    ! Do some analysis
                    if (current_analysis_stage ~= PERFORMED)
                        SuggestionAnalysis(a_buffer);

                    ! if we're done, cancel the timer
                    if (current_analysis_stage == PERFORMED)
                        glk_request_timer_events(0);
                }
                
                ! Event 2 - Window resize
                else if (gg_event-->0 == evtype_Arrange)
                {
                    DrawStatusLine();
                }
                
                else

                ! Event 3 - A Key was Pressed
                if (gg_event-->0 == evtype_CharInput)
                {
                    key = gg_event-->2; ! get the character pressed
    ! awaiting_keypress = false;
                

    ! Different keys require different things
                    switch(key)
                    {
                        ! a newline
                        13, 250, keycode_Return :

                            CompleteSuggestionAnalysis (a_buffer);
                            rv = WriteInSuggestion(a_buffer, cursor_position, (a_buffer-->0 == 1));
                            if (rv > -1) cursor_position = rv - 1;
                            ! -1 because we don't want to put the cursor *after* the last character
                            
    ! glk_set_window((+main-window+).ref_number);
    ! print "Written in suggestion makes line ", rv, " characters long.^";

                            terminated = true;

                        ! escape key
                        keycode_Escape:
                            if (cursor_position > 0)
                            {
                                InsertCharacterAt(' ', a_buffer, cursor_position);
                                !a_buffer->(WORDSIZE + type_position) = ' ';
                                ResetRunningChecks();
                                BlankSuggestion();
                                cursor_position++;
                            }

                        ! a space
                        32:
                            
                            CompleteSuggestionAnalysis (a_buffer);
                            rv = WriteInSuggestion(a_buffer, cursor_position, true);
                            if (rv > -1)
                            {
                                cursor_position = rv;
                            }
                            else if (cursor_position > 0)
                            {
                                InsertCharacterAt(' ', a_buffer, cursor_position);
                                cursor_position ++;
                            }
                        

        ! TODO: moving the cursor drastically affects the suggestion system
        ! eventually...
        ! we need to ensure that the word the player's looking at == the word we're suggesting for

                        ! right arrow
                        keycode_Right:
                            if (cursor_position < a_buffer-->0)
                                cursor_position++;
                        ! left arrow
                        keycode_Left:
                            if (cursor_position > 0)
                                cursor_position--;
                        ! end
                        keycode_End:
                            cursor_position = a_buffer-->0;
                        ! home
                        keycode_Home:
                            cursor_position = 0;

                        ! Tab
                        253, keycode_Tab, 9:
                            ! forces auto-complete
                            ! (so like space, but will write in suggestion
                            ! even if the current word itself is recognised as in the dictionary)

                            CompleteSuggestionAnalysis (a_buffer);
                            rv = WriteInSuggestion(a_buffer, cursor_position, true);
                            if (rv > -1) cursor_position = rv;

                        ! redundant keys are silent
                    
                        keycode_Func1, keycode_Func2,keycode_Func3,keycode_Func4,
                        keycode_Func5,keycode_Func6,keycode_Func7,keycode_Func8,
                        keycode_Func9,keycode_Func10,keycode_Func11,keycode_Func12:

                        ! up arrow - I intend to use this for command recall, later
                        252, keycode_Up, keycode_PageUp:

                            rv = RecallPreviousCommandLine(a_buffer);
                            if (rv > -1)
                            {
                                cursor_position = rv;
                                ResetRunningChecks(false);
                                BlankSuggestion();
        
                                ClearPromptWindow();
                                PrintPromptInWindow();
                            }

                        ! down arrow - currently, these clear the text line (as backspace can be slow)
                        251, keycode_Down, keycode_PageDown:

                            cursor_position = RecallLaterCommandLine(a_buffer);
                            ResetRunningChecks(false);
                            BlankSuggestion();
        
                            ClearPromptWindow();
                            PrintPromptInWindow();

                        ! a backspace
                        127, 8, 254, 249, keycode_Delete:
                            if (cursor_position > 0)
                            {
                                RemoveCharacterAt(a_buffer, cursor_position);
                                cursor_position--;
                                ResetRunningChecks(true);
                                BlankSuggestion();
                            }

                        ! a character
                        default:
                            ! write in the letter
                            InsertCharacterAt(key, a_buffer, cursor_position);
    ! a_buffer->(WORDSIZE + type_position) = key;
                            cursor_position++;
                            
                    }

                    if (~~character_press_engaged)
                    {
                        glk_request_char_event((+key-window+).ref_number);
                    }
                    character_press_engaged = false;
                    break;
                    
                }

            }

        ! We've broken from the loop, which means the text line has changed

            !a_buffer-->0 = input_string_length;

            if (~~terminated)
            {
                ! Cheap analysis pass
                BasicAnalysis(a_buffer, cursor_position);

                ! Print what we've got
                PrintInputLine(a_buffer, cursor_position);

                if (a_buffer-->0 > 0 && a_buffer--> cursor_position ~= ' ')
                {
                    current_analysis_stage = PENDING;

                    SuggestionAnalysis(a_buffer);

                    ! Set up for analysis
                    glk_request_timer_events(TIME_SKIP);

                }
            }
            
        } ! end of main line loop

        ! cancel timer and character events
        glk_cancel_char_event((+key-window+).ref_number);
        glk_request_timer_events(0);

        current_analysis_stage = PERFORMED;

    StoreCommandLine(a_buffer);

        ! tidy up the input line and return
    VM_Tokenise(a_buffer, a_table);

    ! Close any quote window we've got going.
    if (gg_quotewin)
        {
            glk_window_close(gg_quotewin, 0);
    gg_quotewin = 0;
    }

        glk_set_window( (+ main-window +).ref_number);

    ];

    [ InsertCharacterAt char1 in_buffer pos
        i
        ;
        (in_buffer-->0)++;
        for ( i = in_buffer-->0 : i > pos : i-- )
            in_buffer->(i + WORDSIZE) =in_buffer->(i - 1 + WORDSIZE);
        in_buffer->(pos + WORDSIZE) = char1;
    ];

    [ RemoveCharacterAt in_buffer pos
        i;
        if (pos == 0) rfalse;
        for ( i = pos : i <= in_buffer-->0 : i++)
            in_buffer->(i - 1 + WORDSIZE) = in_buffer->(i + WORDSIZE);
        (in_buffer-->0)--;
    ];

    [ CompleteSuggestionAnalysis a_buffer;
        while (current_analysis_stage == PROCESSING) SuggestionAnalysis(a_buffer, true);
        glk_request_timer_events(0);
    ];



    -) after "Keyboard Input" in "Glulx.i6t".