有没有更好的方法来实现Shift + Tab或Decrease Indent?

时间:2010-08-26 10:34:52

标签: c# wpf

这是我实现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;
}

代码看起来很乱,我想知道是否有更好的方法。

2 个答案:

答案 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)

我正在思考,因为我从未实现过文本编辑器。

如果用具有缩进属性的对象表示每一行,这会在行的渲染中反映出来。然后很容易增加和减少缩进。