I was considering this idea, my conclusion:
The worst part is the text area control... why? Well textareas have quite a bunch of features:
- Cursor:
- To move the cursor when the the user click you need to get in which character of the text the cursor is. To do this you need to calculate the line where the user clicked (this can be done with the y coordinate of the mouse and the line height), then calculate the character position (with something like Font:getWrap and the x coordinate of the mouse)
- The cursor also moves with the arrows keys and whenever a character is added. This is easy, just increment or decrement the pointer
- Characters are added at the cursor position, you can do this with string.sub and concatenation
- Pressing the up or down arrow keys and moving up to a similar position in the line above, this is really hard too, maybe with a method similar to the mouse cursor.
- Selecting text:
- This is the hardest, dragging the mouse while the left click is pressed, selects a bunch of text, to do this you can get the first cursor with the same method described above, and then have a second cursor which is dynamic (while the mouse is still pressed) and after the click is released get the selection.
- Selections are also modified when the shift key is pressed and an arrow is pressed.
- If you move to the left or right the selection is unselected.
- When you press a key, the selection gets replaced.
- forget about complicated things like tabulating the selection when tab is pressed or such.
Followed by this you have syntax highlighting, to do this, you need a parser as said by Ivan, this should parse the whole document and split the different zones, lets said you have this text:
Code: Select all
function (a)
a = {"Hello",123}
end
The parser should return a table like:
Code: Select all
line[1]={
{"function",type="function"};
{" "};
{"(",type="operator"}
{"a",type="none"}
{")",type="operator"}
}
line[2]={
{" a ",type="none"}
{"= ",type="operator"};
{"{",type="table"};
{"\"Hello\"",type="string"}
{",",type="operator"}
{"123",type="number"}
{"}",type="table"}
}
line[3]={
{"end",type="function"}
}
There are many of this things, an example is LPeg which I dont like and needs a C library to work, but is commonly used for this tasks.
You dont need to parse the file on every update, since most of it will be unchanged, just parse the lines that where modified when a character is input or a selection is deleted. But again, you dont need to parse the whole file, just the part that changed
Then you need to interpret the parser output and print it to the screen, with the appropriate fonts and colors. Also you need to know how much width each word uses so that they are correctly separated. For that you could turn that table into something a library like Robyn's richtext library understands, and leave the printing work to it.
I may suggest you frustum-cull this text, because as Kikito said, printing to the screen is an expensive function when doing it so many times, so you will need to know which parts of the text should be displayed and which ones are not needed so you dont waste time printing unseen text.
You will also need a scrollbar. That was the first thing I did, because it is lot of math, It is in one of my repositories (Fruit), you can use it if you want
Copying and pasting was made easier with the new love.system functions ([g/s]etClipboard()) so there is nothing to worry over there.