News:

When registered with our forums, feel free to send a "here I am" post here to differ human beings from SPAM bots.

Main Menu

Minor "bug" in automatic indenting of braces

Started by Ceniza, November 25, 2008, 07:27:34 PM

Previous topic - Next topic

Ceniza

It's been a while since I noticed this little inconvenience, but I think it's never too late to comment about it.

Code::Blocks tries to be smart by automatically indenting the next line of code if what you just wrote is an opening brace '{', and it also tries to be smart by putting the closing brace '}' at the same level. However, if you have an opening brace followed by a closing brace, and you press enter when the cursor is in the middle, you end up with the closing brace being indented. I'm quite sure the fix is very simple, when you know the right place to look for it. I would love to fix this myself, but only pin-pointing the right place to look for it would take me quite some time, which I don't really have now. I may have some time this Thursday to look into it, but if someone else feels like fixing a bug that sounds quite simple, go ahead :)

danselmi

Hi

With this patch:

--- cbeditor.cpp (revision 5322)
+++ cbeditor.cpp (working copy)
@@ -2574,7 +2574,7 @@
                 switch(control->GetLexer())
                 {
                     case wxSCI_LEX_CPP:
-                        if (b == _T('{'))
+                        if ( b == _T('{') && control->GetCharAt(pos) != _T('}') )
                         {

smart-indent will work as expected if the closing brace is immediately behind
the cursor before pressing enter. I'm able to prepare a version which is
checking the next non blank char, if you think this is needed.
spell checker plugin: [url="http://developer.berlios.de/projects/spellchecker/"]http://developer.berlios.de/projects/spellchecker/[/url]
nassi shneiderman plugin: [url="http://developer.berlios.de/projects/nassiplugin"]http://developer.berlios.de/projects/nassiplugin[/url]

Ceniza

One that checks the next non-blank character sounds good, if it also removes those blank characters in between. At least you have found the right place to modify that behavior :D

danselmi

Hi

This patch

--- cbeditor.cpp (revision 5318)
+++ cbeditor.cpp (working copy)
@@ -172,7 +172,31 @@
         }
         return 0;
     }
+    wxChar  GetNextNonWhitespaceCharOfLine(int position = -1, int *pos = 0)
+    {
+        cbStyledTextCtrl* control = m_pOwner->GetControl();
+        if (position == -1)
+            position = control->GetCurrentPos();

+        while (position < control->GetLength())
+        {
+            wxChar c = control->GetCharAt(position);
+            if ( c == _T('\n') || c ==  _T('\r') )
+            {
+                if ( pos ) *pos = position;
+                return 0;
+            }
+            if ( c !=  _T(' ') && c != _T('\t') )
+            {
+                if ( pos ) *pos = position;
+                return c;
+            }
+            position++;
+        }
+
+        return 0;
+    }
+
     int FindBlockStart(int position, wxChar blockStart, wxChar blockEnd, bool skipNested = true)
     {
         cbStyledTextCtrl* control = m_pOwner->GetControl();
@@ -2571,15 +2595,25 @@

                 // SMART INDENTING - THIS IS LANGUAGE SPECIFIC, BUT CURRENTLY ONLY IMPLEMENTED FOR C/C++ AND PYTHON
                 wxChar b = m_pData->GetLastNonWhitespaceChar();
+                int nonblankpos;
+                wxChar c = m_pData->GetNextNonWhitespaceCharOfLine(pos, &nonblankpos);
                 switch(control->GetLexer())
                 {
                     case wxSCI_LEX_CPP:
                         if (b == _T('{'))
                         {
-                            if(control->GetUseTabs())
-                                indent << _T('\t'); // 1 tab
+                            if ( c != _T('}') )
+                            {
+                                if(control->GetUseTabs())
+                                    indent << _T('\t'); // 1 tab
+                                else
+                                    indent << wxString(_T(' '), control->GetTabWidth()); // n spaces
+                            }
                             else
-                                indent << wxString(_T(' '), control->GetTabWidth()); // n spaces
+                            {
+                                control->SetCurrentPos(nonblankpos);
+                                control->DeleteBack();
+                            }
                         }
                         break;

will search for the next non blank char on the line and removes these blank chars.
spell checker plugin: [url="http://developer.berlios.de/projects/spellchecker/"]http://developer.berlios.de/projects/spellchecker/[/url]
nassi shneiderman plugin: [url="http://developer.berlios.de/projects/nassiplugin"]http://developer.berlios.de/projects/nassiplugin[/url]

MortenMacFly

Quote from: danselmi on November 26, 2008, 01:17:35 PM
This patch

+                int nonblankpos;
+                wxChar c = m_pData->GetNextNonWhitespaceCharOfLine(pos, &nonblankpos);

I would do this calculation inside the switch clause for the cpp lexter and after (inside) the check for the opening bracket to minimise CPU load like this:

                    case wxSCI_LEX_CPP:
                        if (b == _T('{'))
                        {
                            int nonblankpos;
                            wxChar c = m_pData->GetNextNonWhitespaceCharOfLine(pos, &nonblankpos);
                            if (c != _T('}'))
                            {
                                if(control->GetUseTabs())
                                    indent << _T('\t'); // 1 tab
                                else
                                    indent << wxString(_T(' '), control->GetTabWidth()); // n spaces
                            }
                            else
                            {
                                control->SetCurrentPos(nonblankpos);
                                control->DeleteBack();
                            }
                        }
                        break;
Compiler logging: Settings->Compiler & Debugger->tab "Other"->Compiler logging="Full command line"
C::B Manual: [url="https://www.codeblocks.org/docs/main_codeblocks_en.html"]https://www.codeblocks.org/docs/main_codeblocks_en.html[/url]
C::B FAQ: [url="https://wiki.codeblocks.org/index.php?title=FAQ"]https://wiki.codeblocks.org/index.php?title=FAQ[/url]

danselmi

you are right:

--- cbeditor.cpp (revision 5318)
+++ cbeditor.cpp (working copy)
@@ -172,7 +172,31 @@
         }
         return 0;
     }
+    wxChar  GetNextNonWhitespaceCharOfLine(int position = -1, int *pos = 0)
+    {
+        cbStyledTextCtrl* control = m_pOwner->GetControl();
+        if (position == -1)
+            position = control->GetCurrentPos();

+        while (position < control->GetLength())
+        {
+            wxChar c = control->GetCharAt(position);
+            if ( c == _T('\n') || c ==  _T('\r') )
+            {
+                if ( pos ) *pos = position;
+                return 0;
+            }
+            if ( c !=  _T(' ') && c != _T('\t') )
+            {
+                if ( pos ) *pos = position;
+                return c;
+            }
+            position++;
+        }
+
+        return 0;
+    }
+
     int FindBlockStart(int position, wxChar blockStart, wxChar blockEnd, bool skipNested = true)
     {
         cbStyledTextCtrl* control = m_pOwner->GetControl();
@@ -2576,10 +2600,23 @@
                     case wxSCI_LEX_CPP:
                         if (b == _T('{'))
                         {
-                            if(control->GetUseTabs())
-                                indent << _T('\t'); // 1 tab
+                            int nonblankpos;
+                            wxChar c = m_pData->GetNextNonWhitespaceCharOfLine(pos, &nonblankpos);
+                            if ( c != _T('}') )
+                            {
+                                if(control->GetUseTabs())
+                                    indent << _T('\t'); // 1 tab
+                                else
+                                    indent << wxString(_T(' '), control->GetTabWidth()); // n spaces
+                            }
                             else
-                                indent << wxString(_T(' '), control->GetTabWidth()); // n spaces
+                            {
+                                if ( pos != nonblankpos )
+                                {
+                                    control->SetCurrentPos(nonblankpos);
+                                    control->DeleteBack();
+                                }
+                            }
                         }
                         break;

this should also work if there are not blanks after the cursor.
spell checker plugin: [url="http://developer.berlios.de/projects/spellchecker/"]http://developer.berlios.de/projects/spellchecker/[/url]
nassi shneiderman plugin: [url="http://developer.berlios.de/projects/nassiplugin"]http://developer.berlios.de/projects/nassiplugin[/url]

Ceniza

It's nice to see it's getting somewhere. I hope I have the time tomorrow to check it, unless someone else decides to commit it.

Ceniza

Sorry, I didn't have the time to check it today... as I expected, and now it's time for me to go to bed.

Hopefully, I'll have some time this weekend.

Ceniza

Well, I finally had the time to check the patch and test it. It's now applied in revision 5328. Thanks danselmi :wink: