这是我实现Shift-Tab或减少缩进的结果... screenr
上的结果if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift && e.Key == Key.Tab)
{
// Shift+Tab
int selStart = txtEditor.SelectionStart;
int selLength = txtEditor.SelectionLength;
string selText = txtEditor.SelectedText;
string text = txtEditor.Text;
// find new lines that are followed by 1 or more spaces
Regex regex = new Regex(Environment.NewLine + @"(\s+)");
Match m = regex.Match(selText);
string spaces;
while (m.Success)
{
GroupCollection grps = m.Groups;
spaces = grps[1].Value;
int i = 0;
// remove 1 space on each loop to a max of 4 spaces
while (i < 4 && spaces.Length > 0)
{
spaces = spaces.Remove(0, 1);
i++;
}
// update spaces in selText
selText = selText.Remove(grps[1].Index, grps[1].Length).Insert(grps[1].Index, spaces);
m = regex.Match(selText, grps[1].Index + spaces.Length);
}
// commit changes to selText to text
text = text.Remove(selStart, selLength).Insert(selStart, selText);
// decrease indent of 1st line
// - find 1st character of selection
regex = new Regex(@"\w");
m = regex.Match(text, selStart);
int start = selStart;
if (m.Success) {
start = m.Index;
}
// - start search for spaces
regex = new Regex(Environment.NewLine + @"(\s+)", RegexOptions.RightToLeft);
m = regex.Match(text, start);
if (m.Success) {
spaces = m.Groups[1].Value;
int i = 0;
while (i < 4 && spaces.Length > 0) {
spaces = spaces.Remove(0, 1); // remove 1 space
i++;
}
text = text.Remove(m.Groups[1].Index, m.Groups[1].Length).Insert(m.Groups[1].Index, spaces);
selStart = m.Groups[1].Index;
}
txtEditor.Text = text;
txtEditor.SelectionStart = selStart;
txtEditor.SelectionLength = selText.Length;
e.Handled = true;
}
代码看起来很乱,我想知道是否有更好的方法。
答案 0 :(得分:3)
就个人而言,我不会使用Regex
。
未经测试,可能需要修改:
public static class StringExtensions
{
// Removes leading white-spaces in a string up to a maximum
// of 'level' characters
public static string ReduceIndent(this string line, int level)
{
// Produces an IEnumerable<char> with the characters
// of the string verbatim, other than leading white-spaces
var unindentedChars = line.SkipWhile((c, index) => char.IsWhiteSpace(c) && index < level);
return new string(unindentedChars.ToArray());
}
// Applies a transformation to each line of a string and returns the
// transformed string
public static string LineTransform(this string text, Func<string,string> transform)
{
//Splits the string into an array of lines
var lines = text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
//Applies the transformation to each line
var transformedLines = lines.Select(transform);
//Joins the transformed lines into a new string
return string.Join(Environment.NewLine, transformedLines.ToArray());
}
}
...
if ((Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift && e.Key == Key.Tab)
{
// Reduces the indent level of the selected text by applying the
// 'ReduceIndent' transformation to each line of the text.
string replacement = txtEditor.SelectedText
.LineTransform(line => line.ReduceIndent(4));
int selStart = txtEditor.SelectionStart;
int selLength = txtEditor.SelectionLength;
txtEditor.Text = txtEditor.Text
.Remove(selStart, selLength)
.Insert(selStart, replacement);
txtEditor.SelectionStart = selStart;
txtEditor.SelectionLength = replacement.Length;
e.Handled = true;
}
修改强>
根据OP的请求为代码添加了注释。
欲了解更多信息:
答案 1 :(得分:0)
我正在思考,因为我从未实现过文本编辑器。
如果用具有缩进属性的对象表示每一行,这会在行的渲染中反映出来。然后很容易增加和减少缩进。