PreviousUpNext

15.4.1402  src/lib/x-kit/widget/edit/eval-mode.pkg

## eval-mode.pkg
#
# Mode for interactive Mythryl evaluation.
#
# See also:
#     src/lib/x-kit/widget/edit/textpane.pkg
#     src/lib/x-kit/widget/edit/millboss-imp.pkg
#     src/lib/x-kit/widget/edit/textmill.pkg
#     src/lib/x-kit/widget/edit/fundamental-mode.pkg

# Compiled by:
#     src/lib/x-kit/widget/xkit-widget.sublib


stipulate
    include package   threadkit;                                # threadkit                     is from   src/lib/src/lib/thread-kit/src/core-thread-kit/threadkit.pkg
    #
#   package ap  =  client_to_atom;                              # client_to_atom                is from   src/lib/x-kit/xclient/src/iccc/client-to-atom.pkg
#   package au  =  authentication;                              # authentication                is from   src/lib/x-kit/xclient/src/stuff/authentication.pkg
#   package cpm =  cs_pixmap;                                   # cs_pixmap                     is from   src/lib/x-kit/xclient/src/window/cs-pixmap.pkg
#   package cpt =  cs_pixmat;                                   # cs_pixmat                     is from   src/lib/x-kit/xclient/src/window/cs-pixmat.pkg
#   package dy  =  display;                                     # display                       is from   src/lib/x-kit/xclient/src/wire/display.pkg
#   package fti =  font_index;                                  # font_index                    is from   src/lib/x-kit/xclient/src/window/font-index.pkg
#   package r2k =  xevent_router_to_keymap;                     # xevent_router_to_keymap       is from   src/lib/x-kit/xclient/src/window/xevent-router-to-keymap.pkg
#   package mtx =  rw_matrix;                                   # rw_matrix                     is from   src/lib/std/src/rw-matrix.pkg
#   package rop =  ro_pixmap;                                   # ro_pixmap                     is from   src/lib/x-kit/xclient/src/window/ro-pixmap.pkg
#   package rw  =  root_window;                                 # root_window                   is from   src/lib/x-kit/widget/lib/root-window.pkg
#   package rwv =  rw_vector;                                   # rw_vector                     is from   src/lib/std/src/rw-vector.pkg
#   package sep =  client_to_selection;                         # client_to_selection           is from   src/lib/x-kit/xclient/src/window/client-to-selection.pkg
#   package shp =  shade;                                       # shade                         is from   src/lib/x-kit/widget/lib/shade.pkg
#   package sj  =  socket_junk;                                 # socket_junk                   is from   src/lib/internet/socket-junk.pkg
#   package x2s =  xclient_to_sequencer;                        # xclient_to_sequencer          is from   src/lib/x-kit/xclient/src/wire/xclient-to-sequencer.pkg
#   package tr  =  logger;                                      # logger                        is from   src/lib/src/lib/thread-kit/src/lib/logger.pkg
#   package tsr =  thread_scheduler_is_running;                 # thread_scheduler_is_running   is from   src/lib/src/lib/thread-kit/src/core-thread-kit/thread-scheduler-is-running.pkg
#   package u1  =  one_byte_unt;                                # one_byte_unt                  is from   src/lib/std/one-byte-unt.pkg
#   package v1u =  vector_of_one_byte_unts;                     # vector_of_one_byte_unts       is from   src/lib/std/src/vector-of-one-byte-unts.pkg
#   package v2w =  value_to_wire;                               # value_to_wire                 is from   src/lib/x-kit/xclient/src/wire/value-to-wire.pkg
#   package wg  =  widget;                                      # widget                        is from   src/lib/x-kit/widget/old/basic/widget.pkg
#   package wi  =  window;                                      # window                        is from   src/lib/x-kit/xclient/src/window/window.pkg
#   package wme =  window_map_event_sink;                       # window_map_event_sink         is from   src/lib/x-kit/xclient/src/window/window-map-event-sink.pkg
#   package wpp =  client_to_window_watcher;                    # client_to_window_watcher      is from   src/lib/x-kit/xclient/src/window/client-to-window-watcher.pkg
#   package wy  =  widget_style;                                # widget_style                  is from   src/lib/x-kit/widget/lib/widget-style.pkg
#   package xc  =  xclient;                                     # xclient                       is from   src/lib/x-kit/xclient/xclient.pkg
#   package xj  =  xsession_junk;                               # xsession_junk                 is from   src/lib/x-kit/xclient/src/window/xsession-junk.pkg
#   package xtr =  xlogger;                                     # xlogger                       is from   src/lib/x-kit/xclient/src/stuff/xlogger.pkg
    #
    

# XXX SUCKO FIXME Does this need to be __premicrothread' for any reason???
    package fil =  file__premicrothread;                        # file__premicrothread          is from   src/lib/std/src/posix/file--premicrothread.pkg
    #
    package evt =  gui_event_types;                             # gui_event_types               is from   src/lib/x-kit/widget/gui/gui-event-types.pkg
    package gts =  gui_event_to_string;                         # gui_event_to_string           is from   src/lib/x-kit/widget/gui/gui-event-to-string.pkg
    package gt  =  guiboss_types;                               # guiboss_types                 is from   src/lib/x-kit/widget/gui/guiboss-types.pkg

    package a2r =  windowsystem_to_xevent_router;               # windowsystem_to_xevent_router is from   src/lib/x-kit/xclient/src/window/windowsystem-to-xevent-router.pkg

    package gd  =  gui_displaylist;                             # gui_displaylist               is from   src/lib/x-kit/widget/theme/gui-displaylist.pkg

    package pp  =  standard_prettyprinter;                      # standard_prettyprinter        is from   src/lib/prettyprint/big/src/standard-prettyprinter.pkg
    package tlj =  textlines_junk;                              # textlines_junk                is from   src/lib/x-kit/widget/edit/textlines-junk.pkg

                                                                # compiler                      is from   src/lib/core/compiler/compiler.pkg
    package err =  compiler::error_message;                     # error_message                 is from   src/lib/compiler/front/basics/errormsg/error-message.pkg
    package sci =  compiler::sourcecode_info;                   # sourcecode_info               is from   src/lib/compiler/front/basics/source/sourcecode-info.pkg

    package ct  =  cutbuffer_types;                             # cutbuffer_types               is from   src/lib/x-kit/widget/edit/cutbuffer-types.pkg
#   package ct  =  gui_to_object_theme;                         # gui_to_object_theme           is from   src/lib/x-kit/widget/theme/object/gui-to-object-theme.pkg
#   package bt  =  gui_to_sprite_theme;                         # gui_to_sprite_theme           is from   src/lib/x-kit/widget/theme/sprite/gui-to-sprite-theme.pkg
#   package wt  =  widget_theme;                                # widget_theme                  is from   src/lib/x-kit/widget/theme/widget/widget-theme.pkg


    package boi =  spritespace_imp;                             # spritespace_imp               is from   src/lib/x-kit/widget/space/sprite/spritespace-imp.pkg
    package cai =  objectspace_imp;                             # objectspace_imp               is from   src/lib/x-kit/widget/space/object/objectspace-imp.pkg
    package pai =  widgetspace_imp;                             # widgetspace_imp               is from   src/lib/x-kit/widget/space/widget/widgetspace-imp.pkg

    #    
    package gtg =  guiboss_to_guishim;                          # guiboss_to_guishim            is from   src/lib/x-kit/widget/theme/guiboss-to-guishim.pkg

    package b2s =  spritespace_to_sprite;                       # spritespace_to_sprite         is from   src/lib/x-kit/widget/space/sprite/spritespace-to-sprite.pkg
    package c2o =  objectspace_to_object;                       # objectspace_to_object         is from   src/lib/x-kit/widget/space/object/objectspace-to-object.pkg

    package s2b =  sprite_to_spritespace;                       # sprite_to_spritespace         is from   src/lib/x-kit/widget/space/sprite/sprite-to-spritespace.pkg
    package o2c =  object_to_objectspace;                       # object_to_objectspace         is from   src/lib/x-kit/widget/space/object/object-to-objectspace.pkg

    package g2p =  gadget_to_pixmap;                            # gadget_to_pixmap              is from   src/lib/x-kit/widget/theme/gadget-to-pixmap.pkg
    package m2d =  mode_to_drawpane;                            # mode_to_drawpane              is from   src/lib/x-kit/widget/edit/mode-to-drawpane.pkg

    package idm =  id_map;                                      # id_map                        is from   src/lib/src/id-map.pkg
    package im  =  int_red_black_map;                           # int_red_black_map             is from   src/lib/src/int-red-black-map.pkg
#   package is  =  int_red_black_set;                           # int_red_black_set             is from   src/lib/src/int-red-black-set.pkg
    package sm  =  string_map;                                  # string_map                    is from   src/lib/src/string-map.pkg

    package r8  =  rgb8;                                        # rgb8                          is from   src/lib/x-kit/xclient/src/color/rgb8.pkg
    package r64 =  rgb;                                         # rgb                           is from   src/lib/x-kit/xclient/src/color/rgb.pkg
    package g2d =  geometry2d;                                  # geometry2d                    is from   src/lib/std/2d/geometry2d.pkg
    package g2j =  geometry2d_junk;                             # geometry2d_junk               is from   src/lib/std/2d/geometry2d-junk.pkg

    package e2g =  millboss_to_guiboss;                         # millboss_to_guiboss           is from   src/lib/x-kit/widget/edit/millboss-to-guiboss.pkg
    package gtj =  guiboss_types_junk;                          # guiboss_types_junk            is from   src/lib/x-kit/widget/gui/guiboss-types-junk.pkg

    package frm =  frame;                                       # frame                         is from   src/lib/x-kit/widget/leaf/frame.pkg
    package sl  =  screenline;                                  # screenline                    is from   src/lib/x-kit/widget/edit/screenline.pkg
    package p2l =  textpane_to_screenline;                      # textpane_to_screenline        is from   src/lib/x-kit/widget/edit/textpane-to-screenline.pkg
    package wt  =  widget_theme;                                # widget_theme                  is from   src/lib/x-kit/widget/theme/widget/widget-theme.pkg

                                                                # compiler                      is from   src/lib/core/compiler/compiler.pkg
    package cs  =  compiler::compiler_state;                    # compiler_state                is from   src/lib/compiler/toplevel/interact/compiler-state.pkg
    package ds  =  compiler::deep_syntax;                       # deep_syntax                   is from   src/lib/compiler/front/typer-stuff/deep-syntax/deep-syntax.pkg
    package pcs =  compiler::per_compile_stuff;                 # per_compile_stuff             is from   src/lib/compiler/front/typer-stuff/main/per-compile-stuff.pkg
    package raw =  compiler::raw_syntax;                        # raw_syntax                    is from   src/lib/compiler/front/parser/raw-syntax/raw-syntax.pkg

#    package pcs =  per_compile_stuff;                          # 

    package em  =  eval_mill;                                   # eval_mill                     is from   src/lib/x-kit/widget/edit/eval-mill.pkg
    package mt  =  millboss_types;                              # millboss_types                is from   src/lib/x-kit/widget/edit/millboss-types.pkg
    package fm  =  fundamental_mode;                            # fundamental_mode              is from   src/lib/x-kit/widget/edit/fundamental-mode.pkg
    package mm  =  minimill_mode;                               # minimill_mode                 is from   src/lib/x-kit/widget/edit/minimill-mode.pkg

#   package que =  queue;                                       # queue                         is from   src/lib/src/queue.pkg
    package nl  =  red_black_numbered_list;                     # red_black_numbered_list       is from   src/lib/src/red-black-numbered-list.pkg
    package ml  =  makelib;                                     # makelib                       is from   src/lib/core/makelib/makelib.pkg
    package ci  =  compile_imp;                                 # compile_imp                   is from   src/lib/x-kit/widget/edit/compile-imp.pkg

    package psx =  posixlib;                                    # posixlib                      is from   src/lib/std/src/psx/posixlib.pkg

    tracefile   =  "widget-unit-test.trace.log";

    nb = log::note_on_stderr;                                   # log                           is from   src/lib/std/src/log.pkg

# Temporary test code:
    stdout_redirect = psx::stdout_redirect;
    stderr_redirect = psx::stderr_redirect;
Dummy1 = ci::Compile_Option; # XXX SUCKO FIXME temporary hack to ensure ci compiles during early development.

herein

    package eval_mode {                                 # 
        #
        exception EVAL_MODE__STATE;                                                                             # Our per-pane persistent state (currently none).
                                                                                                                # Note that our eval_mill half DOES have private state -- see Eval_Mill_State in   src/lib/x-kit/widget/edit/eval-mill.pkg
                                                                                                                # Wee access that via the editfn 'mill_extension_state' field -- see below.

        fun input_done          (arg:           mt::Editfn_In)                                                  # We bind this to RET to signal when eval-buffer code entry is complete.
            :                                   mt::Editfn_Out
            =
            {   arg ->    { args:                       List( mt::Prompted_Arg ),                               # Args read interactively from user per our __editfn.args spec.
                            textlines:                  mt::Textlines,
                            point:                      g2d::Point,                                             # As in Point_And_Mark.
                            mark:                       Null_Or(g2d::Point),                                    # 
                            lastmark:                   Null_Or(g2d::Point),                                    # 
                            screen_origin:              g2d::Point,                                             # Origin of pane-visible text relative to textmill contents:  (0,0) means we're showing top of buffer at top of textpane.
                            visible_lines:              Int,                                                    # Number of lines of text visible in pane.
                            readonly:                   Bool,                                                   # TRUE iff contents of textmill are currently marked as read-only.
                            keystring:                  String,                                                 # User keystroke that invoked this editfn.
                            numeric_prefix:             Null_Or( Int ),                                         # ^U "Universal numeric prefix" value for this editfn if supplied by user, else NULL.
                            edit_history:               mt::Edit_History,                                       # Recent visible states of textmill, to support undo functionality.
                            pane_tag:                   Int,                                                    # Tag of pane for which this editfn is being invoked.  This is a small int for human/GUI use.
                            pane_id:                    Id,                                                     # Id  of pane for which this editfn is being invoked.
                            mill_id:                    Id,                                                     # Id  of mill for which this editfn is being invoked.
                            to:                         Replyqueue,                                             # The name makes   foo::pass_something(imp) to {. ... }   syntax read well.
                            widget_to_guiboss:          gt::Widget_To_Guiboss,                                  # 
                            mill_to_millboss:           mt::Mill_To_Millboss,
                            #
                            mainmill_modestate:         mt::Panemode_State,                                     # Any persistent per-mode state (e.g., private state for fundamental-mode.pkg) for main mill is available via this.
                            minimill_modestate:         mt::Panemode_State,                                     # Any persistent per-mode state (e.g., private state for    minimill-mode.pkg) for mini mill is available via this.
                            #
                            mill_extension_state:       Crypt,
                            textpane_to_textmill:       mt::Textpane_To_Textmill,                               # NB: We're running in textmill's microthread to guarantee atomicity, so invoking blocking textpane_to_textmill.* fns is likely to deadlock.
                            mode_to_drawpane:           Null_Or( m2d::Mode_To_Drawpane ),                       # This will be non-NULL iff we specified a non-NULL draw_*_fn in our mt::PANEMODE value at bottom of file (which we do not do in this package).
                            valid_completions:          Null_Or( String -> List(String) )                       # If this is non-NULL then user is entering a commandname or filename or millname(=buffername) on the modeline, and given fn returns all valid completions of string-entered-so-far.
                          };

# nb {. sprintf "input_done/AAA    -- eval-mode.pkg"; };
                eval_mill_state
                    =
                    em::decrypt__eval_mill_state  mill_extension_state;
# nb {. sprintf "input_done/BBB    -- eval-mode.pkg"; };

                eval_mill_state                                                                                 # Much of the following logic is adapted from  read_eval_print_from_user()  in   src/lib/compiler/toplevel/interact/read-eval-print-loop-g.pkg
                  ->                                                                                            # Putting it here allows customization of the logic without having to frig with  src/lib/compiler/toplevel/interact/read-eval-print-loop-g.pkg
                  { compiler_state_stack:       Ref ((cs::Compiler_State, List(cs::Compiler_State)))
                  };
                    
                (pp::make_standard_prettyprinter_into_buffer [])
                  ->
                  { pp, get_buffer_contents_and_clear_buffer };

                exception END_OF_FILE;

                fun eval_string''  (sourcecode_info:    sci::Sourcecode_Info)
                    =
                    {   parse_string_to_raw_declarations            =  widget_to_guiboss.g.app_to_compileimp.parse_string_to_raw_declarations;
                        compile_raw_declaration_to_package_closure  =  widget_to_guiboss.g.app_to_compileimp.compile_raw_declaration_to_package_closure;
                        link_and_run_package_closure                =  widget_to_guiboss.g.app_to_compileimp.link_and_run_package_closure;

                        options =  [ cs::COMPILER_VERBOSITY pcs::print_expression_value ]                       # Print only value of expression, not its type nor any of the intermediate code representations.
                                :  List( cs::Compile_And_Eval_String_Option );

                        declarations
                            =
                            parse_string_to_raw_declarations { sourcecode_info, pp };

                        apply do_declaration declarations
                            where
                                fun do_declaration (declaration: raw::Declaration)
                                    =
                                    case (compile_raw_declaration_to_package_closure
                                          {
                                            declaration,
                                            sourcecode_info,
                                            pp,
                                            compiler_state_stack => *compiler_state_stack,
                                            options
                                          }
                                         )
                                        #
                                        THE arg =>  {   compiler_state_stack
                                                            :=
                                                            link_and_run_package_closure
                                                              #
                                                              { sourcecode_info, pp }
                                                              #
                                                              arg;      

                                                                                                                # NB: There's a potential problem here in that I believe output is currently only inserted in the
                                                                                                                #     buffer once execution is complete.  If execution is lengthy or indefinite, this will be a
                                                                                                                #     problem.  For now I'm only intending to use this facility for quickly executing expressions
                                                                                                                #     so I'm blowing this off for now.   -- 2015-09-27 CrT   XXX SUCKO FIXME 
                                                    };

                                        NULL    =>  ();
                                    esac;
                            end;
                    };

                fun eval_string'  stream
                    =
                    {   error_consumer
                            =
                            {
                                consumer =>   \\ (s: String) =  {
                                                                    pp.lit s;
                                                                },
                                flush    =>   \\ () = (),
                                close    =>   \\ () = ()
                            };
                        source =    sci::make_sourcecode_info
                                      {
                                        file_name           =>  "*eval*",                       # "filename"
                                        line_num            =>  1,
                                        source_stream   =>  stream,
                                        error_consumer,
                                        is_interactive  =>  FALSE                               # FALSE suppresses attempts to print interactive prompts -- see  src/lib/compiler/front/parser/main/mythryl-parser-guts.pkg
                                      };

                        eval_string'' source
                        except
                            exception'
                                =
                                {   sci::close_source   source;
                                    #
                                    case exception'
                                        #
                                        END_OF_FILE =>   (); 
                                        _           =>   raise exception exception';
                                    esac;
                                };
                    };

                fun eval_string  (code: String)
                    =
                    safely::do
                      {
                        open_it  =>   {. fil::open_string  code; },
                        close_it =>   fil::close_input,
                        cleanup  =>   \\ _  =  ()
                      }
                      eval_string';

                string_to_eval
                    =
                    case mark
                        #
                        THE mark => tlj::get_selection_as_string { mark, point, textlines };
                        
                        NULL     => {   line =  mt::findline (textlines, point.row);
                                        #
                                        line =  if (string::is_prefix  "eval: "  line)  string::extract (line, 6, NULL);
                                                else                                    line;
                                                fi;
                                        line;
                                    };
                    esac;
# nb {. sprintf "input_done/CCC string_to_eval s='%s'    -- eval-mode.pkg"  string_to_eval; };
                    
                eval_string   string_to_eval;

                pp::flush_prettyprinter pp;                                                             # Next probably makes this redundant.
                pp::close_prettyprinter pp;                                                             # Flush text from internal prettyprint datastructures into prettyprint's output stream/buffer.

                output = get_buffer_contents_and_clear_buffer ();                                       # Get contents of prettyprint's output stream/buffer.
# nb {. sprintf "input_done/EEE string::length_in_bytes(output)=%d    -- eval-mode.pkg" (string::length_in_bytes output); };
# nb {. sprintf "input_done/FFF output=<<<%s>>>    -- eval-mode.pkg" output; };
# nb {. sprintf "input_done/GGG string::length_in_bytes(output)=%d    -- eval-mode.pkg" (string::length_in_bytes output); };

                textlines = tlj::append_lines (textlines, [ output ]);

                textlines = tlj::append_lines (textlines, [ "\n", "eval: \n" ]);

                point     = tlj::end_of_buffer_point  textlines;

# nb {. sprintf "input_done/ZZZ    -- eval-mode.pkg"; };
                WORK  [ mt::TEXTLINES  textlines,
                        mt::POINT      point
                      ];
            };
        input_done__editfn
            =
            mt::EDITFN (
              mt::PLAIN_EDITFN
                {
                  name   =>  "input_done",
                  doc    =>  "Interactive entry of string in minimill is complete -- harvest the string and reset to display modeline instead of minimill.",
                  args   =>  [],
                  editfn =>  input_done
                }
              );                                my _ =
        mt::note_editfn  input_done__editfn;


        fun eval                (arg:           mt::Editfn_In)                                                  # Interactive user command to start up an eval-mode pane onto an eval-mill -- an interactive facility supporting interactive evaluation of Mythryl.
            :                                   mt::Editfn_Out
            =
            {   arg ->    { args:                       List( mt::Prompted_Arg ),                               # Args read interactively from user per our __editfn.args spec.
                            textlines:                  mt::Textlines,
                            point:                      g2d::Point,                                             # As in Point_And_Mark.
                            mark:                       Null_Or(g2d::Point),                                    # 
                            lastmark:                   Null_Or(g2d::Point),                                    # 
                            screen_origin:              g2d::Point,                                             # Origin of pane-visible text relative to textmill contents:  (0,0) means we're showing top of buffer at top of textpane.
                            visible_lines:              Int,                                                    # Number of lines of text visible in pane.
                            readonly:                   Bool,                                                   # TRUE iff contents of textmill are currently marked as read-only.
                            keystring:                  String,                                                 # User keystroke that invoked this editfn.
                            numeric_prefix:             Null_Or( Int ),                                         # ^U "Universal numeric prefix" value for this editfn if supplied by user, else NULL.
                            edit_history:               mt::Edit_History,                                       # Recent visible states of textmill, to support undo functionality.
                            pane_tag:                   Int,                                                    # Tag of pane for which this editfn is being invoked.  This is a small int for human/GUI use.
                            pane_id:                    Id,                                                     # Id  of pane for which this editfn is being invoked.
                            mill_id:                    Id,                                                     # Id  of mill for which this editfn is being invoked.
                            to:                         Replyqueue,                                             # The name makes   foo::pass_something(imp) to {. ... }   syntax read well.
                            widget_to_guiboss:          gt::Widget_To_Guiboss,                                  # 
                            mill_to_millboss:           mt::Mill_To_Millboss,
                            #
                            mainmill_modestate:         mt::Panemode_State,                                     # Any persistent per-mode state (e.g., private state for fundamental-mode.pkg) for main mill is available via this.
                            minimill_modestate:         mt::Panemode_State,                                     # Any persistent per-mode state (e.g., private state for    minimill-mode.pkg) for mini mill is available via this.
                            #
                            mill_extension_state:       Crypt,
                            textpane_to_textmill:       mt::Textpane_To_Textmill,                               # NB: We're running in textmill's microthread to guarantee atomicity, so invoking blocking textpane_to_textmill.* fns is likely to deadlock.
                            mode_to_drawpane:           Null_Or( m2d::Mode_To_Drawpane ),                       # This will be non-NULL iff we specified a non-NULL draw_*_fn in our mt::PANEMODE value at bottom of file (which we do not do in this package).
                            valid_completions:          Null_Or( String -> List(String) )                       # If this is non-NULL then user is entering a commandname or filename or millname(=buffername) on the modeline, and given fn returns all valid completions of string-entered-so-far.
                          };

# nb {. sprintf "eval/AAA   --eval-mode.pkg"; };
#               eval_mill_state                                                                                 # DO NOT DO THIS!
#                   =                                                                                           # 'eval' is run from an arbitrary pane in order to start up an eval mill+pane, so it is most unlikely that 'mill_extension_state' here will be an eval-mill state.
#                   em::decrypt__eval_mill_state  mill_extension_state;                                         #     -- Voice Of Experience
# nb {. sprintf "eval/BBB   --eval-mode.pkg"; };

                mainmill_modestate.mode
                    ->
                    mt::PANEMODE  pm;

                mill_to_millboss                                                                                # 
                    ->                                                                                          # 
                    mt::MILL_TO_MILLBOSS  m2m;

                textpane_to_textmill'
                    =
                    m2m.get_or_make_textmill                                                                    # It should be OK if millboss-imp finds a mill of an unexpected textmill_extension here
                        #                                                                                       # because we're going to construct the pane for it via textpane_to_textmill.app_to_mill.make_pane_guiplan().
                        { name             => "*eval*",
                          #
                          textmill_options => [ mt::TEXTMILL_EXTENSION  em::eval_mill

                                              ]
                        }
                    :   mt::Textpane_To_Textmill
                    ;


                textpane_to_textmill'
                    ->
                    mt::TEXTPANE_TO_TEXTMILL  t2t;

                t2t.app_to_mill
                    ->
                    mt::APP_TO_MILL  a2m;

                t2t.set_lines [ "eval: \n" ];

                a2m.pass_pane_guiplan to {.
                    #
                    pane_guiplan = #guiplan;

                    do_while_not {.                                                                             # Repeat guipith edit until it takes.  This is needed because other concurrent microthreads may be
                        #                                                                                       # attempting overlapping guipith edits with us.  This avoids deadlock at a (tiny) risk of livelock.
                        get_guipiths             =  widget_to_guiboss.g.get_guipiths;
                        install_updated_guipiths =  widget_to_guiboss.g.install_updated_guipiths;

                        (get_guipiths ())
                            ->
                            (gui_version, guipiths)
                                 #
                                 :  (Int, idm::Map( gt::Xi_Hostwindow_Info ))
                                 ;

                        guipiths =  gtj::guipith_map (guipiths, options)
                                    where
                                        fun do_widget  (w: gt::Xi_Widget_Type):  gt::Xi_Widget_Type
                                            =
                                            case w
                                                #
                                                gt::XI_FRAME
                                                  { id:                 Id,
                                                    frame_widget:               gt::Xi_Widget_Type,             # Widget which will draw the frame surround.
                                                    widget:                     gt::Xi_Widget_Type              # Widget-tree to draw surrounded by frame.
                                                  }
                                                    =>
                                                    case frame_widget
                                                        #
                                                        gt::XI_WIDGET
                                                          {
                                                            widget_id:          Id,
                                                            widget_layout_hint: gt::Widget_Layout_Hint,
                                                            doc:                String                          # Debugging support: Allow XI_WIDGETs to be distinguishable for debug-display purposes.
                                                          }
                                                            =>
                                                            if (not (same_id (widget_id, pane_id)))
                                                                #
                                                                w;
                                                            else
                                                                gt::XI_GUIPLAN pane_guiplan;                    # Replace current pane with new one displaying new mill.
                                                            fi;                                                 # The a2m.make_pane_guiplan here is a wrapped version of the make_pane_guiplan() in this file. 


                                                        _ => w;
                                                    esac;

                                                _ => w;
                                            esac;

                                        options = [  gtj::XI_WIDGET_TYPE_MAP_FN  do_widget  ]
                                                #
                                                : List( gtj::Guipith_Map_Option )
                                                ;
                                    end;

                        install_updated_guipiths                                                                # If this returns FALSE we'll loop and retry.
                            #
                            (gui_version, guipiths);
                    };
                };                                                                                              # do_while_not

                WORK  [ 
                      ];
            };
        eval__editfn
            =
            mt::EDITFN (
              mt::PLAIN_EDITFN
                {
                  name   =>  "eval",
                  doc    =>  "Open an eval-mode pane onto an eval-mill instance.",
                  args   =>  [],
                  editfn =>  eval
                }
              );                                my _ =
        mt::note_editfn  eval__editfn;
#                                               my _ =
# nb {. sprintf "eval__editfn registered   --eval-mode.pkg"; };

        eval_mode_keymap
            =
            keymap
            where
                keymap = mt::empty_keymap;
                #
                keymap = mt::add_editfn_to_keymap (keymap, [ "RET"              ],      input_done__editfn              );
            end;

        stipulate
            #                                                                                                   # Initialize state for the eval-mode part of a textpane at startup.
            fun initialize_panemode_state                                                                       # Our canonical call is from textpane::startup_fn().            # textpane      is from   src/lib/x-kit/widget/edit/textpane.pkg
                  (                                                                                             # To maintain system-global state for mode use the guiboss_types::Gadget_To_Guiboss fns note_global, find_global, drop_global.
                    panemode:                           mt::Panemode,                                           # This will be eval_mode (below).
                    panemode_state:                     mt::Panemode_State,                                     #
                    textmill_extension:                 Null_Or( mt::Textmill_Extension ),                      #
                    panemode_initialization_options:    List(    mt::Panemode_Initialization_Option )           #
                  )
                  :             (       mt::Panemode_State,
                                        Null_Or( mt::Textmill_Extension ),
                                        List(    mt::Panemode_Initialization_Option )
                                )
                =
                {   val =   { id   =>  issue_unique_id (),                                                      # Construct our state.
                              type => "eval_mode::EVAL_MODE__STATE",
                              info => "State for eval-mode.pkg fns",
                              data => EVAL_MODE__STATE
                            };

                    key = val.type;                                                                             # Enter our state into given mt::Panemode_State.
                    #                                                                                           #
                    panemode_state                                                                              #
                      =                                                                                         #
                      { mode => panemode_state.mode,                                                            #
                        data => sm::set (panemode_state.data, key, val)                                         #
                      };                                                                                        #

                    panemode ->  mt::PANEMODE  mm;                                                              # Let our parent panemodes also initialize.
                    #
                    panemode_initialization_options
                      =
                      panemode_initialization_options
                      @ 
                      [ mt::INITIAL_POINT { row => 0, col => 6 }                                                # Put cursor at end of "eval: " prompt.
                      ];
        
                    case mm.parent
                        #
                        THE (parent as mt::PANEMODE p) =>  p.initialize_panemode_state (parent, panemode_state, textmill_extension, panemode_initialization_options);
                        NULL                           =>                                      (panemode_state, textmill_extension, panemode_initialization_options);
                    esac;
                };

            fun finalize_state
                  (
                    panemode:           mt::Panemode,                                                           # This will be eval_mode (below).
                    panemode_state:     mt::Panemode_State
                  )
                  :                     Void
                =
                {   panemode ->  mt::PANEMODE  mm;                                                              # Let our parent panemodes also finalize.
                    #
                    case mm.parent
                        #
                        THE (parent as mt::PANEMODE p) =>  p.finalize_state (parent, panemode_state);
                        NULL                           =>                   (                      );
                    esac;
                };
        herein            

            eval_mode
                =
                mt::PANEMODE
                  {
                    id     =>   issue_unique_id (),
                    name   =>   "Eval",
                    doc    =>   "Interactive Mythryl evaluation.",

                    keymap =>   REF eval_mode_keymap,
                    parent =>   THE fm::fundamental_mode,

                    self_insert_command =>      fm::self_insert_command__editfn,

                    initialize_panemode_state,
                    finalize_state,

                    drawpane_startup_fn           => NULL,
                    drawpane_shutdown_fn          => NULL,
                    drawpane_initialize_gadget_fn => NULL,
                    drawpane_redraw_request_fn    => NULL,
                    drawpane_mouse_click_fn       => NULL,
                    drawpane_mouse_drag_fn        => NULL,
                    drawpane_mouse_transit_fn     => NULL
                  };
        end;

        fun make_pane_guiplan                                                                                   # Synthesize a pane to display textmill's state.  We get invoked by above   gt::XI_GUIPLAN (make_pane_guiplan ()).
              {                                                                                                 # At the moment this is (nearly) a clone of make_textpane::make_pane_guiplan(); if it doesn't diverge we should probably just generalize that fn.
                textpane_to_textmill:   mt::Textpane_To_Textmill,                                               # 
                filepath:               Null_Or( String ),                                                      # make_pane_guiplan should select the pane mode to use based on the filename, but we do not yet do this. XXX SUCKO FIXME.
                textpane_hint:          Crypt
              }
            :                           gt::Gp_Widget_Type
            =
            {
                minipanemode = mm::minimill_mode;
                mainpanemode = eval_mode;

                screenlines_mark =  issue_unique_id ();
                textpane_id      =  issue_unique_id ();

                textmill_spec    =  mt::OLD_TEXTMILL_BY_PORT textpane_to_textmill;

                gt::FRAME
                  ( [ gt::FRAME_WIDGET (textpane::with  { textpane_id,
                                                          screenlines_mark,
                                                          textmill_spec,
                                                          minipanemode,
                                                          mainpanemode,
                                                          options       =>  [ ]
                                                        }
                                       )
                    ],
                    gt::COL
                      [
                        gt::MARK'
                          ( screenlines_mark,
                            "Screenlines",
                            gt::COL
                              [
                                screenline::with
                                  {
                                    paneline  =>  0,
                                    textpane_id,
                                    options     =>  [ sl::DOC               "Screenline 1",
                                                      sl::PIXELS_HIGH_MIN   0,
                                                      sl::STATE             { cursor_at   =>  p2l::NO_CURSOR,
                                                                              selected    =>  NULL,
                                                                              text        =>  "I am a screenline",
                                                                              prompt      =>  "",
                                                                              screencol0  =>  0,
                                                                              background  =>  rgb::white
                                                                            }
                                                    ]
                                  }
                              ]
                          ),
                        gt::FRAME
                          ( [ gt::FRAME_WIDGET (frame::with [ frm::FRAME_RELIEF wt::RAISED ]) ],
                            #
                            screenline::with
                              {
                                paneline  =>  -1,
                                textpane_id,
                                options =>  [ sl::DOC               "Modeline (Screenline -1)",
                                              sl::PIXELS_HIGH_MIN   16,
                                              sl::PIXELS_HIGH_CUT   0.0,
                                              #
                                              sl::STATE { cursor_at  =>  p2l::NO_CURSOR,
                                                          selected   =>  NULL,
                                                          text       =>  "Modeline (Screenline -1)",
                                                          prompt     =>  "",
                                                          screencol0 =>  0,
                                                          background =>  rgb::white
                                                        }
                                            ]
                              }
                          )     
                      ]
                  );
            };

                                                                my _ =
        em::make_pane_guiplan__hack
            :=
            make_pane_guiplan;
    };

end;





Comments and suggestions to: bugs@mythryl.org

PreviousUpNext