B4J Library CodeMirror wrapper and example

After the proof of concept test, here is a wrapper for the CodeMirror javascript libarary which runs quite happily in a Webview.

Current functionality:
  • Highlighting Mode for B4x (and 100+ other languages)
  • Minimal wrapper implementation in library, see the attached CodeEditor for an example of a fuller implementation
  • implemented the available visual themes

In addition, the CodeEditor (also a b4xlib) is an example implementation. The only thing not implemented is file loading and saving as the would really depend on the structure of your project.

Dependencies:

CodeMirrorWrapper:

CodeEditor
  • CodeMirrorWrapper

CMMinimal Implementaion - Project
  • CodeMirrorWrapper

Downloads: (Dropbox)

Both the CodeMirror b4xlib and the CodeMirror project are too large to attach to the forum as they contain the CodeMirror javascript library.
You can download them from my dropbox here:

Version 1.5

  • Separated from the CodeEditor module for easier minimal implementation.
  • Added ReadOnly option
  • Added Themes
    • Requires an allowedthemes List to be passed so they can be validataed against the defined themes.
    • You can pass a subset of the defined themes so only your preferred themes are available.

Update 1.51

  • Small process changes to enable minimal implementation
    • Please download library / Project from the dropbox link
    • added minimal implementation example.

1608562768624.png

Update 1.52
  • Fixed readOnly bug
  • Added LineWrapping
  • Added Autofocus
  • Removed dependency on JScriptEngine
  • Added highlighting for jBasicScript (as B4s)
Please download the b4xlib and or project from my dropbox, links above. If you have a previous version the CodeMirror js library should update itself on first run. If you have made your own changes to the CodeMirror js library, save them first and re-apply.


The CodeEditor.b4xlib and Project and documentation XML files for both libraries are attached.

I hope you find them useful. Let me know how you get on with them.
 

Attachments

  • CodeEditor.b4xlib
    4.7 KB · Views: 305
  • Codeeditor.zip
    7.1 KB · Views: 322
  • CodeEditor.xml
    4.5 KB · Views: 286
  • CMMinimal.zip
    2.1 KB · Views: 300
  • CodeMirrorWrapper.xml
    27.9 KB · Views: 188
Last edited:

LucaMs

Expert
Licensed User
Longtime User
I'm very nervous today, so my questions are going to be silly and annoying probably (luckily I know Steve's amount of patience :)).

Is this a language editor to use in web pages? For example, Erel will use it when B4X will be a single development environment completely on web pages :)?

I read "clichés" that are most likely in computer jargon but of which I probably did not fully understand the meaning, such as: "proof of concept" (?).


The code includes wrappers for Webengine and Worker classes as well as a WebViewWrapper I wrote
?


More than anything else (literal translation that perhaps does not make sense in English), I'm writing all this to waste more time; I mean, right now I'm even more stupid than usual 😄:confused:
 

stevel05

Expert
Licensed User
Longtime User
Well, yes. It is a javascript library that runs in a Web browser. Including the Web View within javafx. The wrapper provides an interface between java and the javascript so it can be controlled. Although it is capable of code completion I have not implemented it as it is not something I would use. I really only use if for the code highlighting.

To my mind, it doesn't seem as robust as the b4x IDE that we know, but it can be run within a java app. There are not many rich text editors available for java.

A proof of concept is another name for an experiment to show that something works.

The wrappers in the library are just classes that wrap the libraries to make them easier to use. I just included the classes instead of providing them as separate b4xlib libraries.

I hope I understood your questions correctly.
 

LucaMs

Expert
Licensed User
Longtime User
I hope I understood your questions correctly.
Yes, thank you, but I am quite ignorant about web programming, including javascript (there is a whole "java world", for decades, which has never fascinated me ... "unfortunately").

The wrappers in the library are just classes that wrap the libraries to make them easier to use.
As a very good ignoramus, I don't know what and which webengine and worker you wrote.

"Workers:" I only very vaguely remember something here on B4X, about B4J server, I think (something to run in background).


Anyway, I'm just raving about it; very bad "evening", pay no attention :)


Thank you, Steve.
 

stevel05

Expert
Licensed User
Longtime User
The Web engine is a java class that controls the webview. The worker class is part of the Web engine. I don't think the names necessarily represent the traditional meanings.
 

max123

Well-Known Member
Licensed User
Longtime User
I'm pretty sure that is part of the internal workings of the CodeMirror library I haven't looked at it for a while.

That's how the setup is supposed to be. I assume that it is a placeholder that gets replaced when code mirror runs.
Many thanks for your Great support @stevel05 , I really appreciated it, expecially because is an old but interesting work and I know that you cannot remember all your code !

No, it won't work with my B4J configurarion, seem not related to CodeMirror, but retalred to WebEngine... JS execute without problems but something is wrong in event return, only READY, SHEDULED, CANCELLED.

I started to port it for B4A, I'm not sure if I can do it, but I ensure you that I will try it.

If someone that have more experience than me want contribute, 2 - 3 or more peoples are better than one.... appreciated.

This is the only code editor I found that can work on B4A.

Many thanks
 
Last edited:

stevel05

Expert
Licensed User
Longtime User
Did you try reacting to the READY event instead of the SUCCEEDED event. I doubt it's that simple but worth a try.
 

max123

Well-Known Member
Licensed User
Longtime User
Did you try reacting to the READY event instead of the SUCCEEDED event. I doubt it's that simple but worth a try.
Yes I will try it.... Thanks Steve

Not sure but I've read in past that B4X IDE use RSyntaxTextArea as code editor, maybe on some files inside B4X installation.

Is this true? Someone have this info ?
As explained I started to wrap it in pure java.
 

Nokia

Active Member
Licensed User
Longtime User
Hi @stevel05,

This codemirror is exactly what I've been looking for my project. Currently using a TextArea field.

I see there is a GetSelectedCode, but do you have a SetSelectedCode?

To implement a search feature...
 

stevel05

Expert
Licensed User
Longtime User
but do you have a SetSelectedCode
I haven't looked at this since writing the wrapper.

GetSelectedCode is a simple call to the API.

B4X:
Public Sub GetSelectedCode As String
    Return ExecuteScript("editor.getSelection();")
End Sub

Looking at the API Documentation it appears that it could be possible to implement setting selections, you would need to do this in JavaScript.
 

Nokia

Active Member
Licensed User
Longtime User
I haven't looked at this since writing the wrapper.

GetSelectedCode is a simple call to the API.

B4X:
Public Sub GetSelectedCode As String
    Return ExecuteScript("editor.getSelection();")
End Sub

Looking at the API Documentation it appears that it could be possible to implement setting selections, you would need to do this in JavaScript.

Thanks for the update, I've changed to a class so I can use it with webview and scene builder. works great, I'm able to get these funcitons to work but having trouble figuring out one.

B4X:
Public Sub IsSelected() As Boolean
    Return ExecuteScript("editor.somethingSelected();")
End Sub
Public Sub ReplaceSelectedCode(Value As String, Selection As Boolean)
    Dim sSelect As String = "start"
    If Selection = True Then
        sSelect = "around"
    End If

    ExecuteScript($"editor.replaceSelection("${Value}","${sSelect}");"$)
    
End Sub
Public Sub GetLineCount() As Int
    Return ExecuteScript("editor.lineCount();")
End Sub
Public Sub EditUndo()
     ExecuteScript("editor.undo();")
End Sub
Public Sub EditRedo()
    ExecuteScript("editor.redo();")
End Sub
Public Sub CommentLine()
    
    Dim ch As Char = ExecuteScript($"editor.getCursor("string");"$)

'    Log(ExecuteScript($"editor.getCursor("head");"$)

    ExecuteScript($"editor.lineComment(5,0);"$)
End Sub

I'm having problem with understanding the commentLine(), the documentation says:

doc.getCursor(?start: string) → {line, ch}Retrieve one end of the primary selection. start is an optional string indicating which end of the selection to return. It may be "from", "to", "head" (the side of the selection that moves when you press shift+arrow), or "anchor" (the fixed side of the selection). Omitting the argument is the same as passing "head". A {line, ch} object will be returned.

lineComment(from: {line, ch}, to: {line, ch}, ?options: object)Set the lines in the given range to be line comments. Will fall back to blockComment when no line comment style is defined for the mode.

Any idea on how to set this up?
 

Attachments

  • Screenshot 2023-02-09 201342.jpg
    Screenshot 2023-02-09 201342.jpg
    226.5 KB · Views: 72

stevel05

Expert
Licensed User
Longtime User
doc.getCursor returns a JSObject object from which you can extract the line and ch members:

B4X:
Public Sub GetCursor As Map
    Dim JSO As JavaObject = ExecuteScript("doc.getCursor()") 'Returns a JSObject Object 
    Return CreateMap("line": JSO.RunMethod("getMember",Array("line")),"ch":JSO.RunMethod("getMember",Array("ch")))
End Sub

Usage:

B4X:
Dim M As Map = CodeMirrorWrapper1.GetCursor
Log(M.Get("line"))
Log(M.Get("ch"))

Using the lineComment requires more javascript knowledge / time than I currently have. There is an example here which may help, there are more if you search.
 

Nokia

Active Member
Licensed User
Longtime User
doc.getCursor returns a JSObject object from which you can extract the line and ch members:

B4X:
Public Sub GetCursor As Map
    Dim JSO As JavaObject = ExecuteScript("doc.getCursor()") 'Returns a JSObject Object
    Return CreateMap("line": JSO.RunMethod("getMember",Array("line")),"ch":JSO.RunMethod("getMember",Array("ch")))
End Sub

Usage:

B4X:
Dim M As Map = CodeMirrorWrapper1.GetCursor
Log(M.Get("line"))
Log(M.Get("ch"))

Using the lineComment requires more javascript knowledge / time than I currently have. There is an example here which may help, there are more if you search.

Thanks for the update, so JSObject is a property:value type setup right?

If so, what is the purpose of "getMember"?
 
Top