My brother Speed and I have spent many happy hours in the past week discussing LeoWapp (Leo as a web app). My firm conclusion is that LeoWapp will be straightforward! I expect to have working code in a matter of weeks. This is a *simpler *project than Leo's console gui.
This post is intended for Leo's devs, especially Joe Orr. This post explains why the design must be as it is. No real knowledge of Leo's code is needed. I'll explain all required concepts as I go along. *Big picture* LeoWapp will have two components: 1. A *browser gui* for Leo, written in python, enabled by Leo's --gui=browser command-line option. 2. A *web component*, say *leowapp.py*, based on mod_http.py. leowapp.py will be written in python, but it will create a page containing significant javascript code. That's all! This is the simplest design that could possibly meet the requirements discussed below. To start LeoWapp, users will use --gui=browser on the command line. This will start a python server in Leo's gui code and a javascript server in the web page. Later, we may well wrap the code in Docker or other virtual machine. As explained in another post <https://groups.google.com/forum/#!topic/leo-editor/Gy6eMQdZq3g>, we can mostly ignore security concerns during development. However, Speed is investigating these issues as we speak. *Terminology* Speed and I use the words "python" and "javascript" as synecdoches <https://en.wikipedia.org/wiki/Synecdoche>. Aa part stands for the whole. Instead of saying, "the javascript code running on Leo's web page in the browser sends a message to the python server running in Leo's gui code", I'll just say, "javascript sends a message to python". *Leo must have a new gui* A new gui because is the one and *only *way to get all of Leo's features without rewriting all of Leo in javascript. Happily, this is relatively straightforward. All of Leo's guis implement the so-called *High Level Interface*. Leo's core code knows (almost) *nothing *about what gui is being used. For Qt, for example, the qt gui code translates calls to the high-level interface into calls to Qt methods. Furthermore, *only* the Qt gui code knows anything about handling Qt events. The situation will be exactly the same for the browser gui. The browser gui will implement the high-level interface, calling the javascript code to implement the intended actions. The browser gui code (python) will also handle events generated by javascript. The details of the interaction between python and javascript constitute the *Private Interface*. We can change the private interface at any time, including after first release, because Leo's core will have absolutely no knowledge of it. *About leowapp.py* This plugin will be based initially on mod_http.py. The javascript DOM can easily generate all required gui events. leowapp.py will translate those events to messages on the private interface. The final form of the javascript is an open question. We'll likely start with jQuery. *Debugging and testing* As with the console gui, a top priority will be to run unit tests *using the browser gui*. There will be complications involved in making this happen, but this work will instantly pay off. I'll be running Leo on a local machine, so the python code can call g.trace as usual. No need for fancy logging. It would be possible to *mirror* the browser outline by showing the Qt version of the outline in addition to the browser view. Speed and I call this *two-headed Leo*. It's not clear whether this is worth doing, but as a thought experiment it helps clarify the messages that must pass over the private interface. *Requirements* We want the user to be able do any of the following *from the browser:* 1. Ctrl-B (execute-script). 2. Alt-x<command-name><return> 3. Alt-x<command-prefix><tab> 4. Select a new node. These requirements will drive the design of the private interface. At present, I know only the general shape of the solution. But clearly, it is *not possible* for the private api to enumerate all possible interactions explicitly. Instead, a chain of messages must pass between python and javascript, very similar to how the Qt gui code interacts with Qt. Several examples should make this clear. *execute-script*: Suppose the body text contains just `g.es("hello")` Here's what happens with the Qt gui, and any other gui: - Leo discovers the script by starting with the body and expanding section references and @others. Leo uses c.p.b (not gui calls) to get the body text, and p2.b to get another other required body text. - Leo passes the script to exec, with a namespace that includes c, g and p. - The executing script, via g.es, calls c.frame.log.put, which is part of the high-level interface. - c.frame.log.put calls the corresponding gui code, which writes to actual Qt widget. - Depending on what Qt method gets called, Qt may generate events, which the Qt gui code handles or ignores. Exactly the same thing will happen with the browser interface, regardless of the complexity of the executed script. *Minibuffer*: Leo's minibuffer code uses only the high-level interface, iirc, so all is well. If there are problems we could always add optional methods to the high-level interface. *Tab completion in the minibuffer*: The high-level interface include methods to discover the text (in the gui) of any widget, so once again no new code needs to be written. However, javascript might shortcut the process of typing completion if that were useful. *Select a new node*: This is the acid test. I'll do this as soon as possible to ensure that there are no gotchas. The *base *tree.select method should be used *as is* by all guis. That is, guis are *not* supposed to override this method. I am confident that this will remain to be true for the browser gui, but the private interface should suffice to handle any complications. *Non issues* Nothing need be done to disable existing plugins. Gui-related plugins, such as todo.py, already must test g.app.gui.guiName() to see whether they are compatible with the present gui. Only minimal changes will be needed to Leo's core. Just as with the console gui, Leo will support the --gui=browser option with a small piece of code in leoApp.py. This code will creates and starts the gui The gui is responsible for implementing the event loop, etc. *Summary* Leo's browser gui will allow access to all of Leo's features from the browser. This gui will implement the full High Level Interface and will use the private interface to communicate with the browser. The private interface connects the python and javascript code. It can be freely modified at any time, including after development. The private interface will define *commands *sent from python to javascript, and *events *sent from javascript to python. Speed thinks that synchronous events will simplify the code. We'll see. I have intentionally slid past many potential complications. I know from implementing 5 or 6 previous guis that all such complications can be handled relatively easily. The browser gui is likely to be *much easier* to do than the console gui. The new design is the simplest thing that could possibly work, and the simplest thing that could meet all requirements. Imo, it's time to start coding. Please let me know if I have forgotten anything important. I will be doing the coding. Speed is working on packaging and security issues. These will come into play if we ever want to allow remote access to LeoWapp. Edward -- You received this message because you are subscribed to the Google Groups "leo-editor" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at https://groups.google.com/group/leo-editor. For more options, visit https://groups.google.com/d/optout.
