Help with formatting module & some feature suggestions

Started by fbfans, Today at 01:45:03 AM

Previous topic - Next topic

fbfans

Dear Paul,help me!
It's me again – I hope you don't mind me bothering you once more. I've seen your continuous new releases, and I really appreciate your hard work.

I've always wanted to have auto‑formatting while typing, similar to what QB64 does. So I tried to write a module (modformatter.inc) that formats a line immediately after it's entered – mainly adding spaces around operators and such simple things. (I'm a beginner and my code is quite messy, so I'm a bit embarrassed to share it.) I tested the module and it basically works. Then I included my module in frmonmainnotify.inc and added the following code:
case chr(13) ' ENTER KEY PRESSED
        pDoc->AutoCompleteType = AUTOCOMPLETE_NONE
        AttemptAutoInsert()
    ' ===== 新增:格式化上一行(开始)=====
                       pDoc->AutoCompleteType = AUTOCOMPLETE_NONE
                             AttemptAutoInsert()
                             
                             dim nLine as long = pDoc->GetCurrentLineNumber()
                             if nLine > 0 then
                                  dim strPrevLine as string = pDoc->GetLine(nLine - 1)
                                  dim sTrim as string = trim(strPrevLine)
                                 
                                  ' 跳过空行和单行注释
                                  if sTrim <> "" and left(sTrim, 1) <> "'" then
                                        ' 检测是否在多行注释内
                                        dim hEdit as HWND = pDoc->hWndActiveScintilla
                                        dim lineStart as long = SciExec(hEdit, SCI_POSITIONFROMLINE, nLine - 1, 0)
                                        dim style as long = SciExec(hEdit, SCI_GETSTYLEAT, lineStart, 0)
                                        if style <> SCE_B_MULTILINECOMMENT then
                                             dim fmtPrevLine as string = AddSpacesAroundOperators(strPrevLine)
                                             if strPrevLine <> fmtPrevLine then
                                                  pDoc->SetLine(nLine - 1, fmtPrevLine)
                                             end if
                                        end if
                                  end if
                             end if
                             ' ===== 新增:格式化上一行(结束)=====
After recompiling, the formatting works, but it breaks the auto‑indentation. With only one level of indentation it works fine, but with two levels (nested blocks) it stops auto‑indenting. I also tried not to format immediately – instead I posted a message to a queue to process it later – but the problem remains.
case chr(13)
        dim nLine as long = pDoc->GetCurrentLineNumber()
        if nLine > 0 then
            ' 保存行号,稍后处理
            gPendingFormatLine = nLine - 1
            PostMessage(HWND_FRMMAIN, MSG_USER_FORMAT_LINE, 0, 0)
        end if
This has been bothering me for a long time. Could you please tell me what I'm doing wrong? Any help would be greatly appreciated.

Additionally, I downloaded and tried the new release immediately. Unfortunately, the TODO list garbled text problem is still there. I also attempted to convert the encoding inside frmoutput.inc, but my skills aren't good enough and I failed. Here are a few small suggestions I'd like to raise – hope you can consider them:

1.The TODO list garbled‑text issue is critical for non‑Latin users.
2.Double‑click on the tab bar to create a new tab (new file).
3.Tiko is based on afxNova; the original winfbe seems to have an AFX help document. Why isn't it included in Tiko? It would be very helpful for learning the afxNova library.
4.Can variable names be auto‑completed with the same case as the first time they were typed, and when renaming, all occurrences of the same variable change together – like in QB64PE?
5.Tiko already collects user‑defined functions – could we set a theme colour for them?
6.Since the sidebar is already crowded with icons, maybe a separate toolbar would be a good idea. And it'd be nice if the sidebar could be clicked to show/hide, like the status bar.
7.Auto‑insert should also auto‑complete for SCOPE, NAMESPACE, etc.

P.S. – I also tried to implement auto‑insert for multi‑line comments and for SCOPE/NAMESPACE blocks with the following code (which I inserted into OnAutoInsert). I'm including it here in case it's useful:
' /'/'/多行注释
     if (left(strPrevLine, 3) = "/' ") or (strPrevLine = "/'") then
         strFill = vbcrlf & FillString(space(nSpaces)) & "'/"
         SciExec(hEdit, SCI_ADDTEXT, len(strFill), strptr(strFill))
         
         if trim(strPrevLine) = "/'" then
              curPos = SciExec(hEdit, SCI_POSITIONFROMLINE, nLine - 1, 0) + NumTabsFromSpaces(nSpaces) + 2
         else
              curPos = curPos + NumTabsFromSpaces(nSpaces)
         end if
         
         SciExec(hEdit, SCI_SETSEL, curPos, curPos)
         exit function
    end if
    2、增加namespace,scope自动补全
        a、在 select case idBlockType段最后加上:
        case BLOCK_STATEMENT_SCOPE:            sStartMatch = "SCOPE":            sEndMatch = "END SCOPE"
        case BLOCK_STATEMENT_NAMESPACE:    sStartMatch = "NAMESPACE ":    sEndMatch = "END NAMESPACE"
        b、在上面多选注释后,或者在while/wend后面增加
        '''''''''''''
        ' SCOPE/END SCOPE
        if (left(strPrevLine, 6) = "SCOPE ") or (strPrevLine = "SCOPE") then
            strFill = FillString(space(nSpaces + IndentSize))
            if CanCompleteBlockStatement(pDoc, BLOCK_STATEMENT_SCOPE) then
                strFill = strFill & vbcrlf & FillString(space(nSpaces)) & "end scope" & vbcrlf
            end if         
            SciExec(hEdit, SCI_ADDTEXT, len(strFill), strptr(strFill))
            curPos = curPos + NumTabsFromSpaces(nSpaces + IndentSize )
            SciExec(hEdit, SCI_SETSEL, curPos, curPos)
            exit function
        end if
         
         '''''''''''''
        ' NAMESPACE/END NAMESPACE
        if (left(strPrevLine, 10) = "NAMESPACE ") or (strPrevLine = "NAMESPACE") then
            strFill = FillString(space(nSpaces + IndentSize))
            if CanCompleteBlockStatement(pDoc, BLOCK_STATEMENT_NAMESPACE) then
                strFill = strFill & vbcrlf & FillString(space(nSpaces)) & "end namespace" & vbcrlf
            end if         
            SciExec(hEdit, SCI_ADDTEXT, len(strFill), strptr(strFill))
            curPos = curPos + NumTabsFromSpaces(nSpaces + IndentSize )
            SciExec(hEdit, SCI_SETSEL, curPos, curPos)
            exit function
        end if
Attached is the Chinese localization file for v1.3.2. Also, the lack of BBCode support here makes posting a bit inconvenient.

Paul Squires

Thanks for the new Chinese language file. I have included it for the next release.

You have given me a lot to think about. I'll work through your questions and try to post some answers. It might take a while to get answers for everything.

As I make changes, I post them all in the Tiko development branch on Github. I am currently in the middle of a fairly large redesign of the UI with most notably being the Find/Replace functionality. I have changed it from VS Code style to Zed Editor style. It is not 100% working yet but it is getting close. I will be moving some of the toolbar icons, etc.
Paul Squires
PlanetSquires Software

Paul Squires

To fix the TODO garbled Chinese text, replace the ctxParser.GetLine() function located in modParser.inc with the following code:  (Hopefully this will work for you. It seemed to work with some Chinese text that I pasted into a Tiko document).

'':::::
function ctxParser.GetLine() as boolean
    this.ReadToEOL()
   
    dim as string st = mid( *this.text, this.s + 1, this.i - this.s)
    this.fullLine.utf8 = st
   
    this.s = this.i
    return true
end function
Paul Squires
PlanetSquires Software

Paul Squires

Double-clicking on the tab bar to create a new empty file:

Add the following code to the frmTopTabs_WndProc() function located in the frmTopTabs.inc file:

    case WM_LBUTTONDBLCLK
        ' If doubleclicking in the unused client area of the tab control then
        ' add a new file. We do not track the actual unused area, so we need to
        ' test whether the double click occured over a Tab or over the Action Panel.
        if ( getHotTabHitTest(hwnd) = -1 ) andalso _
          ( isMouseOverRect(hwnd, gTTabCtl.rcActionPanel) = false ) then
          PostMessage( HWND_FRMMAIN, WM_COMMAND, MAKEWPARAM(IDM_FILENEW, 0), 0 )
        end if
Paul Squires
PlanetSquires Software

Paul Squires

Quote3.Tiko is based on afxNova; the original winfbe seems to have an AFX help document. Why isn't it included in Tiko? It would be very helpful for learning the afxNova library.
There are better sources for this information that having it included within Tiko. The best location is directly from José's repository itself: https://github.com/JoseRoca/AfxNova/tree/main/docs

Fellow forum user hajubu has also created an AfxNova help viewer that may work for you. You can find the latest files at this link: https://www.planetsquires.com/protect/forum/index.php?topic=4834.msg36490
Paul Squires
PlanetSquires Software

Paul Squires

QuoteTiko already collects user‑defined functions – could we set a theme colour for them?
This sounds good in concept but implementing such a feature in practice is quite difficult given the way keywords are handled with the Scintilla editing control.
Paul Squires
PlanetSquires Software

Paul Squires

QuoteSince the sidebar is already crowded with icons, maybe a separate toolbar would be a good idea. And it'd be nice if the sidebar could be clicked to show/hide, like the status bar.
I am redesigning parts of the UI so eventually the toolbar may not be as crowded. The sidebar does not already have n icon to allow it to open/hide. However, you can already show/hide the sidebar via the top menu "View / View Side Panel", or better still, by using the faster keyboard shortcut Ctrl+B.
Paul Squires
PlanetSquires Software

Paul Squires

QuoteAutoinsert....

I have implemented the SCOPE/END SCOPE and NAMESPACE/END NAMESPACE. I also implemented the multiline comment autoinsert but I had to change your code a little bit.

I added the code within thecode block that checks the document's styling to see if we are already within a comment block. I also had to move that entire "Select Case" block to just before where IF/THEN autoinsert code. I had to do this because I needed the code that calculates the nSpaces amount.

    ' Get the styling of the current line to determine if we are in a
    ' multiline or single line comment block then abort the autoinsert.
    select case SciExec(hEdit, SCI_GETSTYLEAT, curPos, 0)
        case SCE_B_MULTILINECOMMENT
            '''''''''''''
            ' MULTILINE COMMENTS  /'  '/ 
            if (left(strPrevLine, 3) = "/' ") orelse (strPrevLine = "/'") then
                strFill = FillString(space(nSpaces)) & vbcrlf & FillString(space(nSpaces)) & "'/"
                SciExec(hEdit, SCI_INSERTTEXT, curPos, strptr(strFill))
                curPos += nSpaces
                SciExec(hEdit, SCI_SETSEL, curPos, curPos)
                exit function
            end if
            exit function
        case SCE_B_COMMENT
            ' Allow to continue for single line comments because we want the ENTER
            ' key to position our cursor under the preceeding ' mark.
    end select
   

    ''''''''''
    ' IF/THEN
    '  Before autoindenting an if statement make sure that this
    '  is in fact a multiline if statement.
    if (left(strPrevLine, 3) = "IF " andalso right(strPrevLine, 5) = " THEN") then
        ' Remove the current line because we will add it again below
'etc...
Paul Squires
PlanetSquires Software

Paul Squires

QuoteCan variable names be auto‑completed with the same case as the first time they were typed, and when renaming, all occurrences of the same variable change together – like in QB64PE?
This type of feature has been requested before. Tiko currently does not have the ability to do this because it does not parse and store variable names. Maybe in a future Tiko version after I implement the full FB compiler's parsing code.
Paul Squires
PlanetSquires Software

Paul Squires

Quotemodformatter.inc ....
If you like, you can email me your code and I will try to incorporate it into the editor. I would have to also implement a Setting where the user can enable or disable the auto formatting (similar to turning on or off AutoIndent, etc).

Don't be concerned about the quality or beauty of your code. If you have seen some of the code I've written over the years then you wouldn't be worried about your code. Some of the code within Tiko itself is code that I've carried over from 20 years worth of previous editors that I've written. I cringe when I see that code and I know that I should rewrite it with the knowledge that I have now..... but it works.

My email address is   support@planetsquires.com   if you want to share it.
 
Paul Squires
PlanetSquires Software

fbfans

Thank you very much for your reply.

I immediately applied your code, recompiled, and tested it. The TODO list now works perfectly – I tested with ANSI, UTF‑8 and UTF‑16, and there is no garbled text at all. Great work!

The double‑click to create a new file also works flawlessly. I modified the code to this:
case WM_LBUTTONDBLCLK
    dim tabIdx as integer = getHotTabHitTest(hwnd)
    if tabIdx >= 0 then
        ' Double‑click on a tab → close that tab
        ' If CloseTab only works on the active tab, activate it first
        if gTTabCtl.CurSel <> tabIdx then
            gTTabCtl.SetFocusTab(tabIdx)
        end if
        gTTabCtl.CloseTab(tabIdx)
        frmTopTabs_PositionWindows()
    elseif isMouseOverRect(hwnd, gTTabCtl.rcActionPanel) = false then
        ' Double‑click on empty area (and not on the action panel) → new file
        PostMessage( HWND_FRMMAIN, WM_COMMAND, MAKEWPARAM(IDM_FILENEW, 0), 0 )
    end if
Now I can both open and close files with a double‑click.

One suggestion:
The TODO detection seems too strict – it only recognises ':TODO:' exactly. For example, ' todo: is not recognised, and even correctly formatted TODOs inside multi‑line comments are not detected (this might be a small bug). I'd suggest relaxing the conditions a little – just match any occurrence of todo: (case‑insensitive, maybe with optional leading whitespace or quotes).

I really appreciate your offer to help with my code formatter. Before I ask you to look into it, I feel I should clean up my code a bit – it's currently too messy to present for analysis. I'll tidy it up and then get back to you, hoping you can help me figure out what went wrong.

Best regards, and thank you again. I'm looking forward to your next major release!

José Roca

QuoteI would have to also implement a Setting where the user can enable or disable the auto formatting (similar to turning on or off AutoIndent, etc).

Yes, please. And if it is disabled by default, much better. The only option that I use is auto indentation.