Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

380
LINES

< > BotCompany Repo | #1016118 // Code Editor [edits snippets and files]

JavaX source code (Dynamic Module) [tags: use-pretranspiled] - run with: Stefan's OS

Uses 5402K of libraries. Click here for Pure Java version (24912L/141K).

1  
!7
2  
3  
// TODO: use central transpiler
4  
5  
set flag bindLiveValueListenerToComponent_debug.
6  
//set flag addMenu_debug.
7  
8  
cmodule2 SFEditor {
9  
  // What are we editing?
10  
  O editing; // File or snippet ID
11  
  S remoteText;
12  
  Int snippetType;
13  
  
14  
  S savedText;
15  
  int caretPos;
16  
  int fontSize = 16;
17  
  S fontID = /*#1400030*/#1400031;
18  
  S snippetTitle;
19  
  switchable bool alwaysTranspileHere = true;
20  
  
21  
  transient EditorFrame2 e;
22  
  transient SimpleLiveValue<O> lvEditing;
23  
  transient AutoCompletion autoCompletion;
24  
  transient ReliableSingleThread rstAutoComplete = dm_rst(this, r installAutoComplete);
25  
  transient bool installAutoComplete_first;
26  
  transient Set<S> autoComplete_lastSet;
27  
  transient int autoCompleteRefreshDelay = 1000;
28  
  transient JFastLogView_noWrap transpilationErrorBox;
29  
  transient ReliableSingleThread persistLater = rstWithDelay(10.0, r persistMe);
30  
  transient JButton saveAndTranspileButton;
31  
  
32  
  !include #1016117 // setAndSave etc.
33  
  
34  
  bool warnOnDelete() { ret neq(e.getText(), unnull(remoteText)); }
35  
36  
  void reset {
37  
    cleanMeUp();
38  
    autoCompletion = null;
39  
    autoComplete_lastSet = null;
40  
    start();
41  
  }
42  
  
43  
  void start() swing {
44  
    temp enter();
45  
    installAutoComplete_first = true;
46  
    lvEditing = dm_fieldLiveValue('editing);
47  
    
48  
    e = new EditorFrame2;
49  
    e._setFont(deriveFont(loadFont(fontID), e._getFont().getSize()));
50  
    e._setFontSize(fontSize);
51  
    main.onChangeAndNow(e.textArea, rstAutoComplete);
52  
    
53  
    // Register Ctrl+S
54  
    e.textArea.getInputMap().put(ctrlKeyStroke(KeyEvent.VK_S),
55  
      abstractAction("Save", rThread { saveThen(null) }));
56  
    
57  
    e.setText(savedText);
58  
    load('caretPos);
59  
    setCaretPosition(e.textArea, caretPos);
60  
  }
61  
  
62  
  visual e.panel;
63  
64  
  enhanceFrame {
65  
    e.prepareFrame(f/JInternalFrame);
66  
    minimalFrameSize(f/JInternalFrame, 400, 400);
67  
    reload();
68  
    makeMenus(f);
69  
    awtCalcEvery(f/JInternalFrame.getRootPane(), 1000, r update);
70  
    onPossiblyInternalFrameDeactivated(f/JInternalFrame.getRootPane(), r fullUpdate);
71  
  }
72  
73  
  void makeMenus(Container f) {
74  
    if (f == null) ret;
75  
    bool wasEmpty = countComponents(getMenuBar(f)) < 2; // Search menu is added somewhere else
76  
    //print("Components in menu: " + getComponents(getMenuBar(f)));
77  
    
78  
    addMenu(f, "&View",
79  
      "Bigger font", r { e._setFontSize(setAndSave(fontSize := e._getFontSize()+1)) },
80  
      "Smaller font", r { e._setFontSize(setAndSave(fontSize := max(1, e._getFontSize()-1))) },
81  
      "---",
82  
      "Show snippet in browser", rThread showInBrowser);
83  
      
84  
    addMenu(f, "&New",
85  
      "New text", r newText,
86  
      "New window", rThread { dm_showNewModule(dm_moduleLibID()) });
87  
  
88  
    addMenu(f, "&Load", "Load snippet...", r {
89  
      selectSnippetID(voidfunc(S snippetID) { _loadSnippet(snippetID) });
90  
    }, "Load file...", r {
91  
      selectFile("File to load", voidfunc(File f) { _loadFile(f) });
92  
    }, "Reload", r-thread { // TODO: single thread
93  
      if (editing != null) {
94  
        reload();
95  
        main setText(e.textArea, remoteText);
96  
      }
97  
    });
98  
    
99  
    // There is a weird bug that breaks the bindToComponent magic
100  
    LiveValue<S> lvSaveCmd = mapLiveValue(func(O editing) -> S {
101  
      editing instanceof S ? "Save snippet " + editing
102  
        : editing instanceof File ? "Save file " + f2s((File) editing)
103  
        : "{Save}" }, S.class, lvEditing);
104  
105  
    addMenu(f, "&Save",
106  
      lvSaveCmd, rThread { saveThen(null) },
107  
      "Save as snippet...", r saveAsSnippet,
108  
      "Save as file...", r saveAsFile,
109  
      "Rename snippet...", rThread renameTheSnippet);
110  
    
111  
    addMenu(f, "&Transpile",
112  
      "Save & Quick Transpile", r { transpile(false) },
113  
      "Save & Medium Transpile", r { transpile(true) },
114  
      "---",
115  
      "Show transpilation", r showTranspilation);
116  
      
117  
    //print("Editing: " + editing);
118  
    
119  
    addMenu(f, "&Activate",
120  
      eq(snippetType, snippetType_JavaXDesktop()) ? "Run" : null, rThread runIt,
121  
      isString(editing) ? "Load Module" : null, rThread _loadModule,
122  
      isString(editing) ? "Reload Module" : null, rThread _reloadModule,
123  
      haveMuricaPassword() ? "Reload on server" : null, rThread _butterReload,
124  
      haveMuricaPassword() ? "Transpile quick & reload on server" : null, rThread { transpileAndButterReload(false) },
125  
      haveMuricaPassword() ? "Transpile medium & reload on server" : null, rThread { transpileAndButterReload(true) });
126  
127  
    if (wasEmpty) {
128  
      // add horizontal spacer so icons end up on the right
129  
      addToContainer(getMenuBar(f), Box.createHorizontalGlue());
130  
  
131  
      // Save & medium transpile icon
132  
      addToContainer(getMenuBar(f), 
133  
        jbutton("Save", rThread { saveThen(null) }),
134  
        setToolTip("Save & medium-transpile",
135  
          setBorderPainted(false,
136  
            saveAndTranspileButton = jimagebutton(#1102952, rThread { transpile(true) })))
137  
      );
138  
    }
139  
  }
140  
141  
  void reload {
142  
    if (editing instanceof S) _loadSnippet_noSet((S) editing);
143  
    else if (editing instanceof File) _loadFile_noSet((File) editing);
144  
  }
145  
  
146  
  void update { update(internalFrameActive(e.panel)); }
147  
  void fullUpdate { update(true); }
148  
  void update(bool full) {
149  
    if (e == null) ret; // e.g. if this instance was made by dm_originalFieldValues
150  
    
151  
    S text = e.getText();
152  
    int cp = getCaretPosition(e.textArea);
153  
    if (neq(savedText, text)) {
154  
      setAndSave(savedText := text);
155  
      setAndSave(caretPos := cp);
156  
    } else if (cp != caretPos) {
157  
      caretPos = cp;
158  
      persistLater.trigger();
159  
    }
160  
      
161  
    if (!full) ret;
162  
    S status = remoteText != null && neq(remoteText, text) ? "Changes. " : "";
163  
    Pair<Int, S> p = testBracketHygieneExt(text);
164  
    status += p == null ? "Hygienic" : p.b;
165  
    silentStatus(trim(status));
166  
  }
167  
  
168  
  void status(S s) { silentStatus(infoBoxAndReturn(s)); }
169  
  void silentStatus(S s) { e.setStatus(s); }
170  
  
171  
  void saveThen(Runnable next) {
172  
    fS text = dropCarriageReturn(getText());
173  
    if (editing cast S) {
174  
      status("Saving snippet...");
175  
      thread {
176  
        fS page = editSnippet(editing, text);
177  
        remoteText = text; // TODO: check save result
178  
        status("Saved snippet: " + page);
179  
        callF(next);
180  
      }
181  
    } else if (editing cast File) {
182  
      status("Saving file...");
183  
      thread {
184  
        saveTextFile(editing, text);
185  
        remoteText = text;
186  
        status("Saved file");
187  
        callF(next);
188  
      }
189  
    }
190  
  }
191  
192  
  void renameTheSnippet enter {
193  
    if (!editing instanceof S)
194  
      ret with infoBox("Not editing a snippet");
195  
    S snippetID = cast editing;
196  
    inputText("Rename snippet " + snippetID, snippetTitle(snippetID), voidfunc(S name) {
197  
      renameSnippet(snippetID, snippetTitle = name);
198  
      setModuleName("Editing: " + snippetID + " - " + quote(snippetTitle));
199  
    });
200  
  }
201  
  
202  
  void _butterReload() {
203  
    time { butterReload((S) editing); }
204  
    infoBox("Reloaded in " + lastTiming_format100ms());
205  
  }
206  
207  
  void transpileAndButterReload(bool medium) {
208  
    transpile(medium, onSuccess := r _butterReload);
209  
  }
210  
  
211  
  void transpile(bool medium, O... _) { saveThen(r { _transpile(medium, _) }); }
212  
  
213  
  void _transpile(bool medium, O... _) {
214  
    optPar Runnable onSuccess;
215  
    status("Transpiling...");
216  
    //jdisable(btnEleuReload);
217  
    
218  
    S toTranspile = or(mainTranspilationSnippetFromSrc(getText()), (S) editing);
219  
    S msg = "Transpiling " + toTranspile + "...";
220  
    infoBox(msg);
221  
    thread msg {
222  
      try {
223  
        Pair<Bool, S> p;
224  
        {
225  
          temp tempDisableButton(saveAndTranspileButton);
226  
          p = transpileHereOrOnServer(toTranspile, medium, alwaysHere := alwaysTranspileHere);
227  
        }
228  
        
229  
        awt {
230  
          if (p.a) {
231  
            status("Transpiled OK!");
232  
            hideWindow(transpilationErrorBox);
233  
            transpilationErrorBox = null;
234  
            callFInNewThread(onSuccess);
235  
          } else {
236  
            S text = htmlDecode(htmlDecode(p.b)); /// XXX
237  
            status("Transpilation error. " + text);
238  
            bool first = transpilationErrorBox == null;
239  
            transpilationErrorBox = maximizeFrame(scrollAllTheWayDown(showText_fast_noWrap(transpilationErrorBox, "Transpilation Error", text)));
240  
            if (first) {
241  
              setFrameIcon(#1101268, transpilationErrorBox);
242  
              addButtonsToWindow(transpilationErrorBox, "Medium transpile", r { _transpile(true) });
243  
            }
244  
          }
245  
        }
246  
      } catch print e {
247  
        status("Transpilation problem. " + e);
248  
      }
249  
      //jenable(btnEleuReload);
250  
    }
251  
  }
252  
  
253  
  void _loadSnippet(S snippetID) enter {
254  
    _loadSnippet_noSet(snippetID);
255  
    e.textArea.setText(remoteText);
256  
  }
257  
  
258  
  void _loadSnippet_noSet(S snippetID) {
259  
    remoteText = loadSnippet(snippetID);
260  
    setField(snippetType := getSnippetType(snippetID));
261  
    setAndSave('editing, snippetID);
262  
    setModuleName("Editing: " + snippetID + " - " + quote(snippetTitle = snippetTitle(snippetID)));
263  
    print("_loadSnippet_noSet: Making menus for " + dm_frame() + " of " + className(dm_vis()));
264  
    makeMenus(dm_frame());
265  
  }
266  
  
267  
  void _loadFile(File f) {
268  
    _loadFile_noSet(f);
269  
    e.textArea.setText(remoteText);
270  
  }
271  
  
272  
  void _loadFile_noSet(File f) {
273  
    remoteText = loadTextFile(f);
274  
    setField(snippetType := null);
275  
    setAndSave('editing, f);
276  
    setModuleName("Editing: " + f2s(f));
277  
    makeMenus(dm_frame());
278  
  }
279  
  
280  
  void newText {
281  
    setAndSave(editing := null);
282  
    remoteText = null;
283  
    setField(snippetType := null);
284  
    S lastText = e.getText();
285  
    if (nempty(lastText)) logQuotedWithDate("saved-texts.log", lastText);
286  
    e.setText("");
287  
    setModuleName(programTitle());
288  
  }
289  
  
290  
  void cleanMeUp {
291  
    update(false);
292  
  }
293  
  
294  
  void installAutoComplete {
295  
    if (installAutoComplete_first) installAutoComplete_first = false;
296  
    else sleep(autoCompleteRefreshDelay); // don't update too often
297  
    
298  
    //temp tempMiniLoadingAnim();
299  
  
300  
    Set<S> set = concatListsToSet(allJavaKeywords(), standardFunctionNames(), deepWords(getText()), deepWords(snippetTitle));
301  
      
302  
    if (eq(set, autoComplete_lastSet)) ret;
303  
    autoComplete_lastSet = set;
304  
    
305  
    final new DefaultCompletionProvider provider;
306  
    provider.addCompletions(map(func(S s) -> Completion { new BasicCompletion(provider, s) }, set));
307  
      
308  
    swing {
309  
      if (autoCompletion == null) {
310  
        (autoCompletion = new AutoCompletion(provider)).install(e.textArea);
311  
        call(autoCompletion, 'setHideOnCompletionProviderChange, false);
312  
      } else
313  
        autoCompletion.setCompletionProvider(provider);
314  
    }
315  
  }
316  
  
317  
  void newWindow {
318  
    copyFields(this, new SFEditor(), 'fontSize).start();
319  
  }
320  
  
321  
  void runIt {
322  
    if (editing instanceof S)
323  
      nohupJavax((S) editing);
324  
  }
325  
  
326  
  void saveAsSnippet {
327  
    JTextField tfTitle = jtextfield(snippetTitle);
328  
    JComboBox cbType = jComboBox_javaxTypes();
329  
    JCheckBox cbPublic = jCheckBox("Public", true);
330  
    
331  
    renameSubmitButton("Create snippet", showFormTitled("Save as new snippet",
332  
      "Title:", tfTitle,
333  
      "Type:", cbType,
334  
      "", cbPublic,
335  
      r-thread {
336  
        loading {
337  
          int type = parseFirstInt(getSelectedItem(cbType));
338  
          S title = getTextTrim(tfTitle);
339  
          S snippetID = createSnippet(getText(), title, type, isChecked(cbPublic));
340  
          _loadSnippet_noSet(snippetID);
341  
        }
342  
      }));
343  
  }
344  
  
345  
  void saveAsFile {
346  
    inputFilePath("Save as...", optCast(File, editing), voidfunc(File f) {
347  
      saveTextFile(f, getText());
348  
      _loadFile_noSet(f);
349  
    });
350  
  }
351  
  
352  
  S getText() { ret e.getText(); }
353  
354  
  void _reloadModule enter {
355  
    dm_reloadAllModulesWithSnippetID((S) editing);
356  
  }
357  
358  
  void _loadModule enter {
359  
    dm_addDynamicModuleDialog2((S) editing);
360  
  }
361  
362  
  S snippetID() { ret optCast S(editing); }
363  
364  
  void showTranspilation enter {
365  
    if (snippetID() == null) ret;
366  
    showText("Transpilation of " + snippetID(),
367  
      getServerTranspiledWithoutLibs(snippetID()));
368  
  }
369  
370  
  void showInBrowser {
371  
    if (snippetID() == null) ret;
372  
    openInBrowser(snippetLink(snippetID()));
373  
  }
374  
  
375  
  // API
376  
  
377  
  void setText(S text) enter {
378  
    e.textArea.setText(text);
379  
  }
380  
}

Author comment

Began life as a copy of #1015563

download  show line numbers  debug dex  old transpilations   

Travelled to 17 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, hpgrupgrauku, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, onxytkatvevr, pyentgdyhuwx, pzhvpgtvlbxg, tslmcundralx, tvejysmllsmz, vouqrxazstgt, xrpafgyirdlv

No comments. add comment

Snippet ID: #1016118
Snippet name: Code Editor [edits snippets and files]
Eternal ID of this version: #1016118/114
Text MD5: 4b2f9396554283499d5676e9678f5e6e
Transpilation MD5: 75fa9898640b481ed7e712f28bfc2e50
Author: stefan
Category: javax / gui
Type: JavaX source code (Dynamic Module)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2022-02-26 17:15:17
Source code size: 12366 bytes / 380 lines
Pitched / IR pitched: No / No
Views / Downloads: 614 / 13585
Version history: 113 change(s)
Referenced in: [show references]