G33kDude / RichCode.ahk

A wrapper around a RichEdit control to provide code editing features.
MIT License
16 stars 8 forks source link

Question: Two controls, two syntaxes, remembers last #6

Open lintalist opened 6 years ago

lintalist commented 6 years ago

In the previous version I could add multiple controls in one GUI and set the "language" for each control, which worked well. With this version, it seems it only remembers the last "language" (the most recently added control).

If you type something (just hitting enter will do) in the first control it changes the HTML highlighting to AHK highlighting (you see the colors change or just type something like 'this' for example to see it, this being a "flow". A modified Examples\demo2.ahk to illustrate: (I didn't bother to update to block/unblock code, I did change the ChangeLang: label)

#NoEnv
SetBatchLines, -1
SetWorkingDir, %A_ScriptDir%

#Include %A_ScriptDir%\..
#Include RichCode.ahk
#Include Highlighters\AHK.ahk
#Include Highlighters\CSS.ahk
#Include Highlighters\HTML.ahk
#Include Highlighters\JS.ahk

; Table of supported languages and sample codes for the demo
Codes :=
( LTrim Join Comments
{
    "AHK": {
        "Highlighter": "HighlightAHK",
        "Code": FileOpen(A_ScriptFullPath, "r").Read()
    },
    "HTML": {
        "Highlighter": "HighlightHTML",
        "Code": FileOpen("Language Samples\Sample.html", "r").Read()
    },
    "CSS": {
        "Highlighter": "HighlightCSS",
        "Code": FileOpen("Language Samples\Sample.css", "r").Read()
    },
    "JS": {
        "Highlighter": "HighlightJS",
        "Code": FileOpen("Language Samples\Sample.js", "r").Read()
    },
    "Plain": {
        "Highlighter": "",
        "Code": FileOpen("Language Samples\Sample.txt", "r").Read()
    }
}
)

; Settings array for the RichCode control
Settings :=
( LTrim Join Comments
{
    "TabSize": 4,
    "Indent": "`t",
    "FGColor": 0xEDEDCD,
    "BGColor": 0x3F3F3F,
    "Font": {"Typeface": "Consolas", "Size": 11},
    "WordWrap": False,

    "UseHighlighter": True,
    "HighlightDelay": 200,
    "Colors": {
        "Comments":     0x7F9F7F,
        "Functions":    0x7CC8CF,
        "Keywords":     0xE4EDED,
        "Multiline":    0x7F9F7F,
        "Numbers":      0xF79B57,
        "Punctuation":  0x97C0EB,
        "Strings":      0xCC9893,

        ; AHK
        "A_Builtins":   0xF79B57,
        "Commands":     0xCDBFA3,
        "Directives":   0x7CC8CF,
        "Flow":         0xE4EDED,
        "KeyNames":     0xCB8DD9,

        ; CSS
        "ColorCodes":   0x7CC8CF,
        "Properties":   0xCDBFA3,
        "Selectors":    0xE4EDED,

        ; HTML
        "Attributes":   0x7CC8CF,
        "Entities":     0xF79B57,
        "Tags":         0xCDBFA3,

        ; JS
        "Builtins":     0xE4EDED,
        "Constants":    0xF79B57,
        "Declarations": 0xCDBFA3
    }
}
)

; Add some controls
Gui, Add, DropDownList, gChangeLang vLanguage, AHK||CSS|HTML|JS|Plain
Gui, Add, Button, ym gBlockComment, Block &Comment
Gui, Add, Button, ym gBlockUncomment, Block &Uncomment

; Add the RichCode
RC1 := new RichCode(Settings, "xm w640 h270")
RC2 := new RichCode(Settings, "xm xp w640 h270")
GuiControl, Focus, % RC1.hWnd

; Set its starting contents
GoSub, ChangeLang

Gui, Show
return

GuiClose:
; Overwrite RC, leaving the only reference from the GUI
RC1 := ""
RC2 := ""

; Destroy the GUI, freeing the RichCode instance
Gui, Destroy

; Close the script
ExitApp
return

BlockComment:
; Get the selected language from the GUI
GuiControlGet, Language

; Apply an appropriate block comment transformation
if (Language == "AHK")
    RC.IndentSelection(False, ";")
else if (Language == "HTML")
    RC.SelectedText := "<!-- " RC.SelectedText " -->"
else if (Language == "CSS" || Language == "JS")
    RC.SelectedText := "/* " RC.SelectedText " */"
return

BlockUncomment:
; Get the selected language from the GUI
GuiControlGet, Language

; Remove an appropriate block comment transformation
if (Language == "AHK")
    RC.IndentSelection(True, ";")
else if (Language == "HTML")
    RC.SelectedText := RegExReplace(RC.SelectedText, "s)<!-- ?(.+?) ?-->", "$1")
else if (Language == "CSS" || Language == "JS")
    RC.SelectedText := RegExReplace(RC.SelectedText, "s)\/\* ?(.+?) ?\*\/", "$1")
return

ChangeLang:
; Keep a back up of the contents
if Language
    Codes[Language].Code := RC.Value

; Get the selected language from the GUI
language:="html"
; Set the new highlighter and contents
RC1.Settings.Highlighter := Codes[Language].Highlighter
RC1.Value := Codes[Language].Code
language:="ahk"
RC2.Settings.Highlighter := Codes[Language].Highlighter
RC2.Value := Codes[Language].Code
return
G33kDude commented 6 years ago

What's different in the demo now than before is that the settings array is no longer .clone()ed before being passed to new RichCode() (https://github.com/G33kDude/RichCode.ahk/commit/0038cb87fe0d5c1b677b8042daae732abe9e38c5#diff-f8eef6ba00f60b536f13c9aa431113e7). Because arrays are always passed by reference, creating two RichCodes without cloning means changing settings for one changes them both, since they're both pointing to the same array in memory.

When you're only using one RichCode it's unnecessary to clone which is why I removed it, though maybe it'd be better to show using multiple in the demo. Thoughts?

lintalist commented 6 years ago

Thanks, I thought I'd experimented with adding/removing .Clone() but the 1.1.27.01 bug got in the way I think . Indeed using .Clone() resolves the issue. (I'll use three edit controls in my "editor" GUI).

Adding a simple note to the readme.md would be enough I think:


Multiple controls

If you want to use multiple RichCode controls which share the basic settings (fonts, colors etc) use the .Clone() method when adding a new control:

; Add the RichCode
RC1 := new RichCode(Settings.Clone(), "xm w640 h270")
RC2 := new RichCode(Settings.Clone(), "xm xp w640 h270")
; ....