/// <summary> /// Access characters on this line by index. The line is treated as virtual space. /// Reading at i >= (Count - HasNewLine) returns '\0'. /// Writing at i >= (Count - HasNewLine) pads with ' '</summary> public char this[int i] { get { if (i < 0) { throw new IndexOutOfRangeException($"Character index {i} out of range"); } if (i >= Count) { return('\0'); } return(Text[i]); } set { if (i < 0) { throw new IndexOutOfRangeException($"Character index {i} out of range"); } using (m_rtb.SelectionScope()) { var count = CountNoNL; Select(i, 1); SelectedText = new string(value, 1); } } }
/// <summary>Update the text fields of the about box</summary> private void UpdateUI() { var rtf = m_licence.InfoStringRtf(); if (m_installed_on != null) { var duration = DateTimeOffset.UtcNow - m_installed_on.Value; int d = duration.Days; int h = duration.Hours; int m = duration.Minutes; int s = duration.Seconds; rtf.Append(new Rtf.TextStyle(rtf.TextStyle) { ForeColourIndex = rtf.ColourIndex(m_licence.Valid ? Color.Green : Color.Red) }); rtf.Append("Installed for: "); if (d != 0) { rtf.Append($" {d} days"); } if (d + h != 0) { rtf.Append($" {h} hours"); } if (d + h + m != 0) { rtf.Append($" {m} minutes"); } if (d + h + m + s != 0) { rtf.Append($" {s} seconds"); } rtf.AppendLine(); } using (m_edit_licence.SelectionScope()) m_edit_licence.Rtf = rtf.ToString(); }
/// <summary>Prevents re-entrant calls to UpdateUI. Yes this is the best way to do it /cry</summary> protected override void UpdateUIInternal() { m_edit_match.Text = Pattern.Expr; m_edit_eqv_regex.Text = Pattern.RegexString; m_edit_replace.Text = Pattern.Replace; m_radio_substring.Checked = Pattern.PatnType == EPattern.Substring; m_radio_wildcard.Checked = Pattern.PatnType == EPattern.Wildcard; m_radio_regex.Checked = Pattern.PatnType == EPattern.RegularExpression; m_check_ignore_case.Checked = Pattern.IgnoreCase; m_btn_add.ToolTip(m_tt, IsNew ? "Add this new pattern" : "Save changes to this pattern"); m_btn_add.ImageKey = IsNew ? "add" : "save"; m_btn_add.Enabled = CommitEnabled; // Show/Hide the eqv regex m_table.Height = m_table.PreferredSize.Height; m_split_subs.Top = m_table.Bottom; m_split_subs.Height = m_split_subs.Parent.Height - m_split_subs.Top - 3; // Highlight the match/replace fields if in error var ex0 = Pattern.ValidateExpr(); string tt0 = ex0 == null ? "The pattern used to identify rows to transform.\r\n" + (Pattern.PatnType == EPattern.RegularExpression ? "Capture groups are defined using the usual regular expression syntax for capture groups e.g. (.*),(<tag>?.*),etc\r\n" : "Create capture groups using '{' and '}', e.g. {one},{2},{tag},etc\r\n") : "Invalid match pattern - " + ex0.Message; var ex1 = Pattern.ValidateReplace(); string tt1 = ex1 == null ? "The template for the transformed result.\r\nUse the capture groups (syntax: {1} or {tag}) created in the Match field" : "Invalid replace template - " + ex1.Message; m_lbl_match.ToolTip(m_tt, tt0); m_edit_match.ToolTip(m_tt, tt0); m_lbl_replace.ToolTip(m_tt, tt1); m_edit_replace.ToolTip(m_tt, tt1); m_edit_match.BackColor = Misc.FieldBkColor(ex0 == null); m_edit_replace.BackColor = Misc.FieldBkColor(ex1 == null); // Apply the transform to the test text if not in error if (ex0 == null && ex1 == null) { string[] lines = m_edit_test.Lines; // Preserve the current carot position using (m_edit_test.SelectionScope()) { // Reset the highlighting m_edit_test.SelectAll(); m_edit_test.SelectionBackColor = Color.White; // Apply the transform to each line in the test text m_edit_result.Clear(); for (int i = 0, iend = lines.Length; i != iend; ++i) { m_edit_result.Select(m_edit_result.TextLength, 0); if (i != 0) { m_edit_result.SelectedText = Environment.NewLine; } if (!Pattern.IsMatch(lines[i])) { m_edit_result.SelectedText = lines[i]; } else { int starti = m_edit_test.GetFirstCharIndexFromLine(i); int startj = m_edit_result.TextLength; List <Transform.Capture> src_caps, dst_caps; string result = Pattern.Txfm(lines[i], out src_caps, out dst_caps); m_edit_result.SelectedText = result; // Highlight the capture groups in the test text and the result int j = 0; foreach (var s in src_caps) { m_edit_test.Select(starti + s.Span.Begi, s.Span.Sizei); m_edit_test.SelectionBackColor = Constants.BkColors[j++ % Constants.BkColors.Length]; } j = 0; foreach (var s in dst_caps) { m_edit_result.Select(startj + s.Span.Begi, s.Span.Sizei); m_edit_result.SelectionBackColor = Constants.BkColors[j++ % Constants.BkColors.Length]; } } } } // Updates the caps data based on the line that the cursor's in var line_index = m_edit_test.GetLineFromCharIndex(m_edit_test.SelectionStart); var line = line_index >= 0 && line_index < lines.Length ? lines[line_index] : string.Empty; var groups = new Dictionary <string, string>(); foreach (var name in Pattern.CaptureGroupNames) { groups[name] = string.Empty; } foreach (var cap in Pattern.CaptureGroups(line)) { groups[cap.Key] = cap.Value; } m_caps = groups.ToList(); } m_grid_subs.RowCount = m_caps.Count; m_grid_subs.Refresh(); }
/// <summary>Update UI elements based on the current pattern state</summary> protected override void UpdateUIInternal() { if (Pattern == null) { return; } m_edit_match.Text = Pattern.Expr; m_radio_substring.Checked = Pattern.PatnType == EPattern.Substring; m_radio_wildcard.Checked = Pattern.PatnType == EPattern.Wildcard; m_radio_regex.Checked = Pattern.PatnType == EPattern.RegularExpression; m_check_ignore_case.Checked = Pattern.IgnoreCase; m_check_whole_line.Checked = Pattern.WholeLine; m_check_invert.Checked = Pattern.Invert; m_btn_add.ToolTip(m_tt, IsNew ? "Add this new pattern" : "Save changes to this pattern"); m_btn_add.ImageKey = IsNew ? "add" : "save"; m_btn_add.Enabled = CommitEnabled; // Highlight the expression background to show valid regex var ex = Pattern.ValidateExpr(); var tt = ex == null ? "The pattern used to match rows in the log file." : "Invalid match pattern - " + ex.Message; m_lbl_match.ToolTip(m_tt, tt); m_edit_match.ToolTip(m_tt, tt); m_edit_match.BackColor = Pattern.IsValid ? FieldValid : FieldInvalid; // Update the highlighting of the test text if valid if (Pattern.IsValid) { var lines = m_edit_test.Lines; // Preserve the current caret position using (m_edit_test.SelectionScope()) { // Reset the highlighting m_edit_test.SelectAll(); m_edit_test.SelectionBackColor = Color.White; // Apply the highlighting to each line in the test text for (int i = 0, iend = lines.Length; i != iend; ++i) { int j = 0; foreach (var r in Pattern.Match(lines[i])) { int starti = m_edit_test.GetFirstCharIndexFromLine(i); // Highlight the capture groups in the test text m_edit_test.Select(starti + r.Begi, r.Sizei); m_edit_test.SelectionBackColor = BkColors[j++ % BkColors.Length]; } } } // Updates the caps data based on the line that the cursor's in var line_index = m_edit_test.GetLineFromCharIndex(m_edit_test.SelectionStart); var line = line_index >= 0 && line_index < lines.Length ? lines[line_index] : string.Empty; var groups = new Dictionary <string, string>(); foreach (var name in Pattern.CaptureGroupNames) { groups[name] = string.Empty; } foreach (var cap in Pattern.CaptureGroups(line)) { groups[cap.Key] = cap.Value; } m_grid_grps.DataSource = groups.ToList(); } }