*/}}
Browse Source

Luajit terminal better

YimingWu 9 months ago
parent
commit
a0e57b01da
8 changed files with 112 additions and 38 deletions
  1. 2 0
      la_interface.h
  2. 1 0
      la_kernel.c
  3. 4 21
      la_util.c
  4. 10 0
      la_util.h
  5. 57 0
      resources/la_lualibs.cpp
  6. 8 4
      resources/la_properties.c
  7. 7 2
      resources/la_templates.c
  8. 23 11
      resources/la_widgets.c

+ 2 - 0
la_interface.h

@@ -314,6 +314,7 @@ STRUCTURE(LA){
     char* TerminalInput[512];
     laListHandle TerminalHistories;
     int TerminalIncomplete;
+    int IsTerminalEnter;
 
     lua_State *L;
 
@@ -1088,6 +1089,7 @@ STRUCTURE(laWidget){
 #define LA_UI_FLAGS_PLAIN     (LA_UI_FLAGS_NO_DECAL|LA_UI_FLAGS_NO_EVENT)
 #define LA_TEXT_ALIGN (LA_TEXT_ALIGN_LEFT|LA_TEXT_ALIGN_CENTER|LA_TEXT_ALIGN_RIGHT|LA_TEXT_ALIGN_AUTO)
 
+#define LA_UI_FLAGS_TERMINAL_INPUT LA_UI_FLAGS_COLOR_SPACE_CLAY
 
 #define LA_UI_SOCKET_LABEL_N LA_TEXT_ALIGN_LEFT
 #define LA_UI_SOCKET_LABEL_S LA_TEXT_ALIGN_RIGHT

+ 1 - 0
la_kernel.c

@@ -610,6 +610,7 @@ void logPrintNew(char* format, ...){
 void logClear(){
     laLogEntry*l;
     while(l=lstPopItem(&MAIN.Logs)){ strSafeDestroy(&l->Content); memFree(l); }
+    laNotifyUsers("la.logs");
 }
 
 #ifdef __linux__

+ 4 - 21
la_util.c

@@ -1716,8 +1716,10 @@ void strBeginEdit(laStringEdit **se, char *FullStr){
     }
     if (!nse->Lines.pFirst){
         laStringLine *sl = memAcquireSimple(sizeof(laStringLine));
-        lstAppendItem(&nse->Lines, sl); nse->TotalLines++;
+        lstAppendItem(&nse->Lines, sl); nse->TotalLines=1;
     }
+    laStringLine *sl = strGetCursorLine(nse, 0); int len=strlen(sl->Buf);
+    if(len<nse->CursorBefore){ nse->CursorBefore=len; }
     *se=nse;
 }
 char* strGetEditString(laStringEdit *se, int SelectionOnly){
@@ -2326,26 +2328,6 @@ static int loadline(lua_State *L){
   lua_remove(L, 1);  /* remove line */
   return status;
 }
-void dotty(lua_State *L){
-  int status;
-  const char *oldprogname = progname;
-  progname = NULL;
-  while ((status = loadline(L)) != -1) {
-    if (status == LUA_OK) status = docall(L, 0, 0);
-    report(L, status);
-    if (status == LUA_OK && lua_gettop(L) > 0) {  /* any result to print? */
-      lua_getglobal(L, "print");
-      lua_insert(L, 1);
-      if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0)
-	l_message(lua_pushfstring(L, "error calling " LUA_QL("print") " (%s)",
-				  lua_tostring(L, -1)));
-    }
-  }
-  lua_settop(L, 0);  /* clear stack */
-  fputs("\n", stdout);
-  fflush(stdout);
-  progname = oldprogname;
-}
 
 static int lalua_Log(lua_State *L) {
   int n = lua_gettop(L); int i;
@@ -2370,6 +2352,7 @@ void la_LuaJITLoadLibs(){
     
     luaL_openlibs(MAIN.L);
     lua_register(L,"log",lalua_Log);
+    if(luaL_loadstring(L, LA_LUA_LIB_COMMON) || lua_pcall(L, 0, 0, 0)){ logPrint("    Error loading lagui lua libs"); };
 
     lua_gc(MAIN.L, LUA_GCRESTART, -1);
 }

+ 10 - 0
la_util.h

@@ -718,3 +718,13 @@ void la_PrintLuaJITStatus();
 void la_LuaJITLoadLibs();
 
 int terLoadLine(char* buf, int firstline);
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+extern const char* LA_LUA_LIB_COMMON;
+
+#ifdef __cplusplus
+}
+#endif

+ 57 - 0
resources/la_lualibs.cpp

@@ -0,0 +1,57 @@
+/*
+* LaGUI: A graphical application framework.
+* Copyright (C) 2022-2023 Wu Yiming
+*
+* This program is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "la_5.h"
+
+extern "C" const char* LA_LUA_LIB_COMMON=R"(
+function ddump(tbl, ...)
+    if(type(tbl)~='table') then log("Not a table."); return end
+    local levels=100
+    local dtableonly=0
+    local arg={...}
+    if(select(1,...)) then levels=select(1,...) end
+    if(select(2,...)) then dtableonly=select(2,...) end
+    local checklist = {}
+    local function print_kv(indent,k,v,t)
+        log(indent..t.." "..k,v,""..(t==' ' and type(v) or ""))
+    end
+    local function innerdump(tbl,indent,lv)
+        local tablelist={}; local funclist={}; local otherlist={}
+        checklist[ tostring(tbl) ] = true
+        for k,v in pairs(tbl) do
+            if type(v)=="function" then funclist[k]={v,'f'}
+            elseif type(v)=="table" then tablelist[k]={v,'t'}
+            else otherlist[k]={v,' '} end
+        end
+        for k,v in pairs(tablelist) do
+            print_kv(indent,k,v[1],v[2])
+            if (lv<levels and not checklist[ tostring(v[1]) ]) then innerdump(v[1],indent.."    ",lv+1) end
+        end
+        if(dtableonly==0) then for k,v in pairs(funclist) do print_kv(indent,k,v[1],v[2]) end end
+        if(dtableonly==0) then for k,v in pairs(otherlist) do print_kv(indent,k,v[1],v[2]) end end
+    end
+    checklist[ tostring(tbl) ] = true
+    innerdump( tbl, "", 0)
+end
+
+function tdump(t)
+    ddump(t,100,1)
+end
+
+ffi = require("ffi")
+)";

+ 8 - 4
resources/la_properties.c

@@ -23,9 +23,10 @@ extern struct _tnsMain *T;
 
 void laset_TerminalInput(void* unused, char* content){
     if((!content)||(!content[0])){ MAIN.TerminalInput[0]=0; return; }
-    int len=strlen(content);{
-        //run command;
-        logPrint("%s\n",content);
+    int len=strlen(content);
+    if(MAIN.IsTerminalEnter){
+        if(strSame(content,"clear")){ logClear(); MAIN.TerminalInput[0]=0; return; }
+        logPrint("%s %s\n",MAIN.TerminalIncomplete?"...":">>>",content);
         terLoadLine(content,1);
         MAIN.TerminalInput[0]=0; return;
     }
@@ -1217,7 +1218,10 @@ void la_RegisterInternalProps(){
         p = laAddPropertyContainer("la_main", "LA Root", "LA Root Structure", U'🖴', 0,sizeof(LA), 0,0,2|LA_PROP_OTHER_ALLOC);{
             laAddSubGroup(p, "logs", "Logs", "Application logs", "la_log",0,0,laui_LogItem, -1, 0,0,0,0,0,0,offsetof(LA, Logs), LA_UDF_IGNORE|LA_READ_ONLY);
             laAddStringProperty(p, "terminal_input", "Terminal Input", "Terminal input string", 0,0,0,0,0, offsetof(LA,TerminalInput),0,0,laset_TerminalInput,0,LA_UDF_LOCAL|LA_UDF_IGNORE);
-            
+            ep=laAddEnumProperty(p, "terminal_incomplete", "Terminal Incomplete", "Incomplete input pending in terminal", 0,0,0,0,0,offsetof(LA, TerminalIncomplete),0,0,0,0,0,0,0,0,0,LA_READ_ONLY|LA_UDF_IGNORE);
+            laAddEnumItemAs(ep, "NONE", "None", "Terminal status is normal", 0, 0);
+            laAddEnumItemAs(ep, "INCOMPLETE", "Incomplete", "Terminal has incomplete input pending", 1, 0);
+
             laAddSubGroup(p, "differences", "Differences", "Difference stack (for undo/redo)", "la_difference",0,0,0,offsetof(LA, HeadDifference), 0,0,0,0,0,0,offsetof(LA, Differences), LA_UDF_IGNORE|LA_READ_ONLY);
             sp=laAddSubGroup(p, "panel_templates", "Panel Templates", "Panel templates used to create new panel", "panel_template",0,0,0,-1, 0,0,0,0,0,0,offsetof(LA, PanelTemplates), 0);
             

+ 7 - 2
resources/la_templates.c

@@ -1452,12 +1452,17 @@ void laui_UndoHistories(laUiList *uil, laPropPack *Base, laPropPack *OperatorIns
     }
 }
 void laui_Terminal(laUiList *uil, laPropPack *Base, laPropPack *OperatorInst, laColumn *ExtraColumns, int context){
-    laColumn* c=laFirstColumn(uil);
+    laColumn* c=laFirstColumn(uil),*cl,*cr; laSplitColumn(uil,c,0.4); cl=laLeftColumn(c,2); cr=laRightColumn(c,0);
     laUiItem* g=laMakeGroup(uil,c,"123",0);{ g->State=LA_UI_ACTIVE; g->Flags|=LA_UI_FLAGS_PREFER_BOTTOM;
         laUiList* gu=g->Page; laColumn* gc=laFirstColumn(gu); gu->HeightCoeff=-3;
         laShowItem(gu,gc,0,"la.logs")->Flags|=LA_UI_FLAGS_NO_DECAL;
     }
-    laShowItem(uil,c,0,"la.terminal_input");
+    laUiItem* b=laOnConditionThat(uil,c,laPropExpression(0,"la.terminal_incomplete"));{
+        laShowLabel(uil,cl,"...",0,0)->Flags|=LA_TEXT_MONO|LA_TEXT_ALIGN_RIGHT;
+    }laElse(uil,b);{
+        laShowLabel(uil,cl,">>>",0,0)->Flags|=LA_TEXT_MONO|LA_TEXT_ALIGN_RIGHT;
+    }laEndCondition(uil,b);
+    laShowItem(uil,cr,0,"la.terminal_input")->Flags|=LA_UI_FLAGS_TERMINAL_INPUT|LA_TEXT_MONO;
 }
 void laui_IdleDataManager(laUiList *uil, laPropPack *Base, laPropPack *Extra, laColumn *ExtraColumns, int context){
     laColumn *c=laFirstColumn(uil);

+ 23 - 11
resources/la_widgets.c

@@ -2510,19 +2510,23 @@ int OPMOD_SingleLineString(laOperator *a, laEvent *e){
     char _buf[LA_RAW_CSTR_MAX_LEN] = {0}; char* buf=_buf;
     int NoEvent = ui->Flags&LA_UI_FLAGS_NO_EVENT;
     int NoTooltip=ui->Flags&LA_UI_FLAGS_NO_TOOLTIP;
+    int IsTerminal=ui->Flags&LA_UI_FLAGS_TERMINAL_INPUT;
 
     if (!laIsInUiItem(ui, e->x, e->y)){
         if (ui->State != LA_UI_EDITING){
             ui->State = LA_UI_NORMAL;
             laRedrawCurrentPanel();
             return LA_FINISHED_PASS;
-        }else if ((e->Type & LA_MOUSEDOWN) == LA_MOUSEDOWN){
-            buf=strEndEdit(&uit->Edit, 0);
-            laSetString(&ui->PP, buf); free(buf);
-            laRecordAndPushProp(&ui->PP,0); laMarkPropChanged(&ui->PP);
-            ui->State = LA_UI_NORMAL;
-            laRedrawCurrentPanel();
-            return LA_FINISHED_PASS;
+        }else{
+            if(IsTerminal && (e->Type&LA_KEY_MOUSE_SCROLL)){ return LA_RUNNING_PASS; }
+            if ((e->Type & LA_MOUSEDOWN) == LA_MOUSEDOWN){
+                buf=strEndEdit(&uit->Edit, 0);
+                laSetString(&ui->PP, buf); free(buf);
+                laRecordAndPushProp(&ui->PP,0); laMarkPropChanged(&ui->PP);
+                ui->State = LA_UI_NORMAL;
+                laRedrawCurrentPanel();
+                return LA_FINISHED_PASS;
+            }
         }
     }
 
@@ -2536,12 +2540,20 @@ int OPMOD_SingleLineString(laOperator *a, laEvent *e){
 
     if(e->Type ==LA_KEY_DOWN){
         if (e->key == LA_KEY_ENTER){
-            buf=strEndEdit(&uit->Edit, 0);
+            buf=IsTerminal?strGetEditString(uit->Edit,0):strEndEdit(&uit->Edit, 0);
+            if(IsTerminal){ MAIN.IsTerminalEnter=1; }
             laSetString(&ui->PP, buf); free(buf);
-            laRecordAndPushProp(&ui->PP,0); laMarkPropChanged(&ui->PP);
-            ui->State = LA_UI_NORMAL;
             laRedrawCurrentPanel();
-            return LA_FINISHED_PASS;
+            if(!IsTerminal){
+                laRecordAndPushProp(&ui->PP,0); laMarkPropChanged(&ui->PP);
+                ui->State = LA_UI_NORMAL;
+                return LA_FINISHED_PASS;
+            }else{
+                laGetString(&ui->PP, _buf, &buf);
+                strBeginEdit(&uit->Edit,buf);
+                MAIN.IsTerminalEnter=0;
+                return LA_RUNNING;
+            }
         }else if (e->key == LA_KEY_ESCAPE && ui->State != LA_UI_NORMAL){
             ui->State = LA_UI_NORMAL;
             laRedrawCurrentPanel();