I'm not using UEX, only UE for Windows. But I suppose that UEX works like UE with regard to indent/unindent behavior.
It looks like you have different expectations on the indent/unindent behavior depending on your configuration than what UltraEdit offers. Reading the appropriate help pages may help to understand the indent/unindent feature of UltraEdit. The help pages of interest are:
Word wrap/tab settings
Auto indent new lines
Add indents command
Remove indents command
Tabs to spaces command
Spaces to tabs (all) command
Spaces to tabs (leading) command
However, I try to explain the indent/unindent feature of UltraEdit with my own words very detailed. This explanation is written by what analyzing the indent/unindent behavior of UltraEdit from a user's point of view. I'm not an employee of IDM and I have never seen anything from the source code of UltraEdit.
But before I can really start with my description, I need to introduce first two terms:
- real line
A real line is a line which begins either
- at top of the file, OR
- after a line termination (line-feed for DOS/UNIX files)
AND ends with
- a line termination, OR
- at end of the file.
- displayed line
A displayed line is a line as displayed in active document window. The displayed line is equal the real line if word-wrap feature is not used for active file and the line is not longer than the value set for configuration setting Maximum columns before line wraps.
A real line could be displayed with several displayed lines in case of using word-wrap feature not inserting line terminators on enabling the word-wrap mode, or when the line is really long and exceeds the value of Maximum columns before line wraps.
There are 3 main configuration settings regarding indents:
- Tab stop value
- Indent spaces
- Use spaces in place of tabs
Those 3 settings can be configured individually for different types of files depending on extension of the files. So it is for example possible to use for .c, .cpp and .h files different settings as for .htm, .html and .xml (at least within UltraEdit for Windows).
Tab stop value
This setting defines a not visible alignment grid for text alignments using horizontal tab characters. A horizontal tab character being already present in a file is displayed with the number of spaces required to position the caret after the tab character at next not visible alignment column.
Usually only 1
tab stop value is used which results in an alignment grid with a constant alignment column width. For example a
tab stop value of 4 results in the alignment columns 1, 5, 9, 13, 17, ... with starting column counting with 1 for first column. In other words a horizontal tab character is displayed with at least 1 space and a maximum of 4 spaces depending on current column position of the tab character and of course when using a fixed width font.
I want to add for completeness that it is possible to specify multiple
tab stop values for example for editing tab delimited CSV files, or for assembler files using only tabs for the alignment of the command, the command parameters and the comment.
It is very important to understand that the
tab stop value is only for horizontal tab characters. It has preliminary nothing to do with indents. Well, yes, with using horizontal tab characters for indents it determines secondary also the indents. But the
tab stop value does not define the indent, especially not in case where just spaces or a mixture of tabs and spaces is used for indents.
Indent spaces
This setting is evaluated only if
use spaces in place of tabs is enabled. It defines really the indent, an indent made with spaces. It is only possible to define 1 value. Multiple values like for the
tab stop value cannot be defined as this value defines preliminary the indent and not an alignment grid.
Writers of plain text files often do not distinguish between indent and tab stop. But with a quick look into a word processing application like Word (MS Office) or Write (OpenOffice) and making there an indent and set tab stops for a real line (paragraph), the difference can be easily seen. It is not possible to define multiple indents for a paragraph, but it is possible to specify multiple tab stops for a paragraph.
But programmers need in source files multiple indents, not within a line, but for different lines. Therefore the
indent spaces value defines the standard indent created by inserting spaces at beginning of a real line which can be increased or decreased line by line. In MS Word there is an option which is ON by default which results in modifying the indent of a paragraph when pressing key TAB at beginning of the paragraph instead of inserting a tab character. Text editors cannot modify the indent of a real line by using a hidden formatting tag and therefore must create the indent by inserting spaces or tabs.
And many programmers additionally want often also a hidden alignment grid based on the
indent spaces value for aligning multiple source code lines with nearly same content like the expressions left and right of assignments. This is the reason why the
indent spaces value defines additionally an alignment grid like the
tab stop value. But this alignment grid based on
indent spaces value is secondary (and in my source code files not used at all).
Use spaces in place of tabs
With this setting NOT enabled, pressing the key TAB results in
- inserting a horizontal tab character at caret position if
- nothing is selected AND
- insert mode is currently active;
- replacing the character at caret position by a horizontal tab character if
- nothing is selected AND
- overstrike mode is currently active;
- replacing the current selection by a horizontal tab character if
- the selection starts and ends within the same displayed line;
- inserting at beginning of every real line a horizontal tab character if
- there is a selection which starts on a different displayed line than it ends.
The last feature is used mainly by programmers to increase the indent level of a selected block or at least one line after making a selection ending on beginning of the displayed line below the real line to indent by either using the
Select Line command or pressing SHIFT+DOWN ARROW and key HOME (being configured to always set caret to column 1).
The
indent spaces value is ignored completely as long as setting
use spaces in place of tabs is not enabled. The only setting being used for indents with
use spaces in place of tabs not enabled is the
tab stop value as side effect because of the alignment grid for tab characters.
With enabling
use spaces in place of tabs the
tab stop value is used only for existing horizontal tabs in the file.
But with this setting enabled and depending on current column and next alignment column, pressing the key TAB results in
- inserting 1 or more spaces at caret position if
- nothing is selected AND
- insert mode is currently active;
- replacing the character(s) at caret position by 1 or more spaces if
- nothing is selected AND
- overstrike mode is currently active;
- replacing the current selection by 1 or more spaces if
- the selection starts and ends within the same displayed line;
- inserting at beginning of every real line 1 or more spaces if
- there is a selection which starts on a different displayed line than it ends.
Please note that the alignment grid for inserting the spaces with or without replacing existing characters is defined by the
indent spaces value while a second alignment grid exists for the existing horizontal tabs in the file defined by the
tab stop value.
The feature to
increase the indent of a selection does not try to be smart with taking into account on which column the first non whitespace is placed currently and therefore makes an indent to align the first non whitespace character on a column according to next alignment column. The feature is not a "move first non whitespace character to next alignment column", it is an
increase indent feature. Increasing the indent of a multi-line selection always results in inserting at beginning of the real line a tab character or the number of spaces according to
indent spaces value. That is very simple, but of course with mixed usage of tabs/spaces it may not produce the expected result. I'm explaining below why a smarter approach produces often also not the expected result.
To complete the description on behavior of pressing key TAB, it is necessary to explain also what happens on pressing SHIFT+TAB when there is a selection starting on a different displayed line than it ends. This feature is for decreasing the indent of the selected real lines. If the real line is indented only by tabs or only by spaces, this is quite simple as just 1 tab respectively the number of spaces according to the
indent spaces value must be removed from beginning of the line, or less if the line has less spaces to first non white space character.
But on lines with indents created by spaces and tabs, this task becomes really difficult. Many users think the target for the
decrease indent feature is to align the selected lines on previous alignment column. But that is not the case. The target is to decrease the indent so that the first non whitespace character on each selected real line moves to right by the number of columns according to
tab stop value or
indent spaces value depending on value of
use spaces in place of tabs.
An example:
Indent spaces value defines the indents and the alignment grid and has the value 4. So the alignment columns would be 1, 5, 9, 13, and so on. But the currently selected line has the first non whitespace character at column 11 for some reason. The decrease indent feature removes 4 spaces at beginning of the selected line to get the first non whitespace character at column 7. That is not an alignment column because not a multiple of the indent value. But SHIFT+TAB is not for moving the selected line to previous alignment column, it is for decreasing the indent.
Auto-indent
The auto-indent feature takes the
tab stop value or the
indent spaces value depending on value of
use spaces in place of tabs
- for aligning the first non whitespace character of current line or next line on next/previous alignment column
- in case of the current line contains an indent or unindent string as defined in the syntax highlighting wordfile applied to the active file or the active section
- on hitting key RETURN.
If the indent must not be changed on inserting a new line, the spaces and/or tabs from the current line are copied to the new line. So if the current line contains 1 space, 1 tab and 2 more spaces up to first non whitespace character, the new line contains also 1 space, 1 tab and 2 more spaces as indent.
Add indents command
It is important to read the help (of UltraEdit for Windows v19.10) about this command very carefully to understand what this command is for.
The Add Indents menu item presents a dialog that allows the user to specify the number of spaces to add at the beginning of each of the selected (highlighted) lines.
The purpose of this command is to insert spaces at beginning of real lines. It does never insert tabs. And it does not increase the indent according to
indent spaces value X times. It just inserts X spaces.
So this command is not for programmers. It is mainly for other text writers who want to increase the indent of a text block by inserting spaces at beginning of each real line of the selected block.
Remove indents command
Also this command does not take the
tab stop value or
indent spaces value into account. It is designed for moving the first non whitespace character X columns to left by removing spaces and tabs. Tabs must be also taken into account by this command as without removing tabs the indent would not decrease if the indent is made with just tabs. The entered number defines how many columns the first non whitespace character should move to left and is therefore not a multiplier for the
tab stop value or
indent spaces value.
Tabs to spaces command
This command replaces all horizontal tab characters by 1 or more spaces according to the alignment grid defined by the
tab stop value.
Spaces to tabs (all) command
This command replaces a sequence of spaces defined by the number of the
tab stop value by a tab character independent on where those spaces are located in the file. The command has no language intellisense. So if the current file is highlighted with a syntax highlighting language containing a string definition and there are multiple spaces inside a string, this command replaces also the spaces in the string by tabs.
Spaces to tabs (leading) command
This command replaces a sequence of spaces defined by the number of the
tab stop value by a tab character, but only from beginning of a real line to first non whitespace character in the line.
Why smart indent/unindent works always only partly?
There are IDE written for just a few programming languages which have a smart indent/unindent feature. My experiences with such IDE are that the smart indent/unindent feature produces only in 50% of all cases the right result
for my sources. The other 50% are indented/unindented wrong and it is necessary to manually correct the smart indent/unindent.
The reason is quite simple: there is no rule without exception.
Usually the indent of a source line is a constant multiple of the
indent spaces value, but within a switch statement it depends on the length of the case statements and the actual indent level of the case statement if the code for each case statement is right of the case statement or below.
Example:
Code: Select all
void MyFooClass::logErrorSubnetClient(const IpVerifyClass::EIpSubnet eErrorCode,
const QString& qsIpAddress, const bool bIPv6Address)
{
MultiLangString mlsErrorMessage;
switch(eErrorCode)
{
case IpVerifyClass::eIpSubnet_SubnetId:
mlsErrorMessage.setMlsKey(QSMLS(n_mlsE_ClientIpSubnetId));
break;
case IpVerifyClass::eIpSubnet_Broadcast:
mlsErrorMessage.setMlsKey(QSMLS(n_mlsE_ClientIpSubnetBroadcast));
break;
default:
mlsErrorMessage.setMlsKey(QSMLS(n_mlsE_ClientIpUnknownError));
break;
}
mlsErrorMessage.setArgQString(QSMLS(a_mlsIPv6),bIPv6Address ? "v6" : "");
mlsErrorMessage.setArgQString(QSMLS(a_mlsIpAddress),qsIpAddress);
MainLog::logEntryMls(mlsErrorMessage,CI4sMainLog::eLogError);
}
int MyFooClass::BaseCaseExample(const int foo)
{
int a;
switch(foo)
{
case 1: a = 10;
break;
case 2: a = 15;
break;
default: a = 0;
break;
}
return a;
}
The
indent spaces value is 4 on this example, but not use constantly, see the second switch statement.
Function definitions, function calls and conditions (if, for, while) often span over multiple lines.
Usually I align second, third, ... line on first opening parenthesis as the example above shows for the definition of first function. But there are exceptions if the function definition, function call or condition is already so long that there is not much space anymore for the function parameters or the conditions before maximum line length. The maximum line length has for me in most cases a higher priority than perfect alignment regarding to the line above as I hate scrolling horizontally to see a source code line completely. And of course in general the second, third, ... line of a function definition, function call or a condition is nearly never on an alignment column as defined by the
indent spaces value or the
tab stop value if I would not use always
use spaces in place of tabs.
On the other hand there are also cases where I violate my own rule about maximum code line length when it makes sense for me.
Other situations for not aligned first non whitespace characters are line comments explaining over multiple lines a code block ending finally on 1 more line without a code below the commented code block.
In other words the indents in my C/C++ files are very dynamic. The only constant indent is for lines starting with { or } and the beginning of a statement within such a block with the exception of case statements within a switch statement.
I favor a good readable code by using appropriate indents over using constantly the same alignment everywhere. Of course there are other programmers which have a different point of view. And that is the point: every programmer has its own expectations on how the own written code should be formatted.
A good example is Artistic Style. This tool makes a pretty good job on reformatting a code written by another programmer to own personal formatting style after defining all options to get the wanted output. But Artistic Style fails nevertheless to produce a perfect result for me. That's not the fault of Artistic Style, it is my fault because I want something no tool can ever produce.
Why I think tabs should not be used in source code files?
A small anecdote before I reply to the question above:
I write and read code now since 20 years. So I have a lot of experience in writing code. Two years ago I was forced to open the sources of some very old applications still used which I wrote more than 15 years ago, for adapting and recompiling them for Windows x64 compatibility. I was astonished to see how I formatted my code in the past. I do write my code nowadays much, much better than 10/15/20 years ago. I have used 15 years ago also tabs for indents. So I was not really surprised to see the old code now not well indented because the tab stop value has changed in the meantime for C/C++ files. With using Artistic Style integrated in UltraEdit and some manual adaptations I could reformat all those old sources to my preferred layout nowadays with spending some time. However, if I would have used already just spaces for indents instead of tabs as I use nowadays in the past, I would not have to reformat the old sources at all. Yes, I could have changed temporarily the tab stop value, but that would have been again no permanent solution.
Reasons for using only spaces for indents instead of tabs (and spaces):
- Tab stop value respectively indent value can change. This value is not fixed until end of the world (or your programming life whatever comes first).
- Other programmers viewing or even editing your source files may have different tab stop settings than you.
- Copying parts of a source code using tabs for indents into an email looks often not good in the email as your email application or the email application of the receiver has a different interpretation of tabs as you have set in your text editor/IDE.
- Copying parts of a source code using tabs for indents into a forum post, blog, etc. resulting in being finally stored in an HTML file looks often not good. There is nothing defined in HTML standard on how browsers should display a tab character in a preformatted block. And outside a preformatted block a sequence of spaces/tabs is always displayed as a single space as defined in HTML standard.
- Two versions of a source code file are compared with a text comparison tool. If the text comparison tool has a different setting for the tab stop value than used in text editor on writing the code, the code does not look good and therefore it is more difficult to see the differences.
- Multiple applications are used for viewing or even editing source code files which do not have the same tab stop/indent value settings. It must be taken into account that most applications store user settings per user account. So what is configured in UltraEdit for current account may differ from what is set in UltraEdit for another account like the root account.
As there is no world-wide standard on how to display a text containing horizontal tab characters, it is an illusion to think the look of a source code can be controlled using tabs.
Tabs for indents makes in my point of view only sense when
- the tab stop value never changes,
- the code is viewed and edited only by me and never by any other person,
- the code is viewed and edited only in one application and never in other applications,
- the used user account is never changed.
It is better to use spaces instead of tabs if one of the 4 conditions above cannot be kept guaranteed as X normal spaces are displayed in all applications with X normal spaces (except for HTML files outside a preformatted block).
Reason to use tabs for indents although one of the 4 conditions above cannot be kept:
The source code files are part of a project on which several persons work as a team and there is the project design and coding standard rule to use tabs with a tab stop value of X.
Finally a hint: Source code files containing already spaces and tabs mixed for indents should be reformatted by using first the command
Tabs to spaces and next
Spaces to tabs (leading). That solves very often indentation problems caused by mixed usage of spaces and tabs for indents.