From 816cb801bd6a82973b33247fd9e095811897446a Mon Sep 17 00:00:00 2001 From: Markus Palcer Date: Thu, 23 May 2019 11:15:42 +0200 Subject: [PATCH 1/3] Fixed logcat parser to account for "start of buffer" lines --- AndroidLogViewer/LogcatParser.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/AndroidLogViewer/LogcatParser.cs b/AndroidLogViewer/LogcatParser.cs index 70cf05d..ab271fb 100644 --- a/AndroidLogViewer/LogcatParser.cs +++ b/AndroidLogViewer/LogcatParser.cs @@ -14,12 +14,13 @@ public class LogcatParser private const string TagRegularExpression = "(?[^:]+):"; private const string MessageRegularExpression = "(?.*)"; private static readonly string TrailingLineRegularExpression =$"(?\\s+?){MessageRegularExpression}"; - private static readonly string DefaultLogcatRegularExpression = $"(?{DateTimeRegularExpression}\\s+{PidRegularExpression}\\s+{TidRegularExpression}\\s+{LogLevelRegularExpression}\\s+{TagRegularExpression}\\s+?){MessageRegularExpression}"; - private static readonly string AndroidStudioRegularExpression = $"(?{DateTimeRegularExpression}\\s+{PidRegularExpression}-{TidRegularExpression}[^\\s]+\\s+{LogLevelRegularExpression}/{TagRegularExpression}\\s+?){MessageRegularExpression}"; + private static readonly string DefaultLogcatRegularExpression = $"(?{DateTimeRegularExpression}\\s+{PidRegularExpression}\\s+{TidRegularExpression}\\s+{LogLevelRegularExpression}\\s*{TagRegularExpression}\\s+?){MessageRegularExpression}"; + private static readonly string AndroidStudioRegularExpression = $"(?{DateTimeRegularExpression}\\s+{PidRegularExpression}-{TidRegularExpression}[^\\s]+\\s*{LogLevelRegularExpression}/{TagRegularExpression}\\s+?){MessageRegularExpression}"; + private static readonly string StartOfLogExpression = "(?\\s*---+)(?.*)"; - private static readonly string[] RecognizedRegularExpressions = {DefaultLogcatRegularExpression, AndroidStudioRegularExpression, TrailingLineRegularExpression}; - private static readonly string Pattern = $"^{string.Join("|", RecognizedRegularExpressions.Select(x => $"({x})"))}$"; + private static readonly string[] RecognizedRegularExpressions = {DefaultLogcatRegularExpression, AndroidStudioRegularExpression, TrailingLineRegularExpression, StartOfLogExpression}; + private static readonly string Pattern = $"{string.Join("|", RecognizedRegularExpressions.Select(x => $"^({x})$"))}"; private static readonly Regex RegularExpression = new Regex(Pattern, RegexOptions.Compiled); static LogcatParser() @@ -41,6 +42,7 @@ public static ObservableCollection ReadLogEntries(TextReader reader) if (match.Success) { LogEntry newEntry = null; + if (match.Groups["datetime"].Success) { newEntry = new LogEntry @@ -56,6 +58,13 @@ public static ObservableCollection ReadLogEntries(TextReader reader) pivotEntry = newEntry; } + else if (match.Groups["startoflog"].Success) + { + newEntry = new LogEntry + { + Message = $"--- {match.Groups["message"].Value.Trim()}" + }; + } else if (match.Groups["trailingline"].Success && pivotEntry != null) { var trimmedMessage = match.Groups["message"].Value.Trim(); @@ -72,6 +81,7 @@ public static ObservableCollection ReadLogEntries(TextReader reader) Time = pivotEntry.Time, }; } + if (newEntry != null) result.Add(newEntry); } From 078194757fa2a496a7ae1c6e70b36df64fa008d3 Mon Sep 17 00:00:00 2001 From: Markus Palcer Date: Thu, 23 May 2019 15:29:40 +0200 Subject: [PATCH 2/3] Added command that exports selected log lines (Closes #2) --- AndroidLogViewer/MainWindow.xaml | 4 ++++ AndroidLogViewer/MainWindowViewModel.cs | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/AndroidLogViewer/MainWindow.xaml b/AndroidLogViewer/MainWindow.xaml index fed21e8..f0d641b 100644 --- a/AndroidLogViewer/MainWindow.xaml +++ b/AndroidLogViewer/MainWindow.xaml @@ -286,6 +286,10 @@ + + diff --git a/AndroidLogViewer/MainWindowViewModel.cs b/AndroidLogViewer/MainWindowViewModel.cs index d6e9f73..901f9b3 100644 --- a/AndroidLogViewer/MainWindowViewModel.cs +++ b/AndroidLogViewer/MainWindowViewModel.cs @@ -3,6 +3,7 @@ using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; +using System.Diagnostics; using System.IO; using System.Linq; using System.Net; @@ -49,6 +50,7 @@ public MainWindowViewModel() ExportCommand = new DelegateCommand( () => ShowDialog(new ExportDialogViewModel(_defaultView.OfType().ToArray())).FireAndForget(), () => !string.IsNullOrEmpty(FileName)).ObservesProperty(() => FileName); + ExportSelectionCommand = new DelegateCommand>(x => ShowDialog(new ExportDialogViewModel(x.OfType().ToArray())).FireAndForget()); OpenFileCommand = new DelegateCommand(OpenFile); OpenUrlCommand = new DelegateCommand(OpenUrl); @@ -149,6 +151,8 @@ private bool FilterLogEntries(object x) public ICommand ExportCommand { get; } + public ICommand ExportSelectionCommand { get; } + #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; From 7e0f6fc9db05a2ec9aee699ebd0273e849c4f61e Mon Sep 17 00:00:00 2001 From: Markus Palcer Date: Fri, 24 May 2019 08:50:30 +0200 Subject: [PATCH 3/3] Selected log lines can now be copied to the clipboard (Closese #21) --- AndroidLogViewer/AndroidLogViewer.csproj | 1 + AndroidLogViewer/Command/BindingRedirector.cs | 36 +++++++++++++++++++ .../Dialogs/Export/ExportDialogViewModel.cs | 7 +++- AndroidLogViewer/MainWindow.xaml | 3 ++ AndroidLogViewer/MainWindow.xaml.cs | 19 ++++------ AndroidLogViewer/MainWindowViewModel.cs | 4 ++- 6 files changed, 55 insertions(+), 15 deletions(-) create mode 100644 AndroidLogViewer/Command/BindingRedirector.cs diff --git a/AndroidLogViewer/AndroidLogViewer.csproj b/AndroidLogViewer/AndroidLogViewer.csproj index 8a4eb94..b311a3c 100644 --- a/AndroidLogViewer/AndroidLogViewer.csproj +++ b/AndroidLogViewer/AndroidLogViewer.csproj @@ -58,6 +58,7 @@ MSBuild:Compile Designer + diff --git a/AndroidLogViewer/Command/BindingRedirector.cs b/AndroidLogViewer/Command/BindingRedirector.cs new file mode 100644 index 0000000..ddb9808 --- /dev/null +++ b/AndroidLogViewer/Command/BindingRedirector.cs @@ -0,0 +1,36 @@ +using System.Windows; + +namespace AndroidLogViewer.Command +{ + public class BindingRedirector : DependencyObject + { + public static readonly DependencyProperty LeftProperty = DependencyProperty.Register( + "Left", typeof(object), typeof(BindingRedirector), new PropertyMetadata(default(object), LeftChanged)); + + private static void LeftChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((BindingRedirector) d).Right = e.NewValue; + } + + public object Left + { + get { return (object) GetValue(LeftProperty); } + set { SetValue(LeftProperty, value); } + } + + public static readonly DependencyProperty RightProperty = DependencyProperty.Register( + "Right", typeof(object), typeof(BindingRedirector), new PropertyMetadata(default(object) , RightChanged)); + + private static void RightChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + ((BindingRedirector) d).Left = e.NewValue; + } + + public object Right + { + get { return (object) GetValue(RightProperty); } + set { SetValue(RightProperty, value); } + } + + } +} \ No newline at end of file diff --git a/AndroidLogViewer/Dialogs/Export/ExportDialogViewModel.cs b/AndroidLogViewer/Dialogs/Export/ExportDialogViewModel.cs index 00c0823..d0d0d25 100644 --- a/AndroidLogViewer/Dialogs/Export/ExportDialogViewModel.cs +++ b/AndroidLogViewer/Dialogs/Export/ExportDialogViewModel.cs @@ -97,7 +97,7 @@ private void ExecuteConfirmCommand() } else { - lines = _entries.Select(x=> $"{x.Time} {x.Process} {x.Thread} {x.Level} {x.Tag}: {x.Message}"); + lines = _entries.Select(FormatLogEntry); } @@ -105,5 +105,10 @@ private void ExecuteConfirmCommand() Done(null); } + + public static string FormatLogEntry(LogEntry x) + { + return $"{x.Time} {x.Process} {x.Thread} {x.Level} {x.Tag}: {x.Message}"; + } } } \ No newline at end of file diff --git a/AndroidLogViewer/MainWindow.xaml b/AndroidLogViewer/MainWindow.xaml index f0d641b..20732a1 100644 --- a/AndroidLogViewer/MainWindow.xaml +++ b/AndroidLogViewer/MainWindow.xaml @@ -212,6 +212,9 @@ Style="{StaticResource MonospaceFont}" SelectedIndex="{Binding SelectedLogEntryIndex}" SelectedItem="{Binding Path=SelectedLogEntry, Mode=OneWayToSource}"> + + + ShowDialog(new ExportDialogViewModel(_defaultView.OfType().ToArray())).FireAndForget(), () => !string.IsNullOrEmpty(FileName)).ObservesProperty(() => FileName); ExportSelectionCommand = new DelegateCommand>(x => ShowDialog(new ExportDialogViewModel(x.OfType().ToArray())).FireAndForget()); + CopySelectionCommand = new DelegateCommand>(items => Clipboard.SetText(string.Join("\n", items.OfType().Select(ExportDialogViewModel.FormatLogEntry)))); OpenFileCommand = new DelegateCommand(OpenFile); OpenUrlCommand = new DelegateCommand(OpenUrl); @@ -153,6 +153,8 @@ private bool FilterLogEntries(object x) public ICommand ExportSelectionCommand { get; } + public ICommand CopySelectionCommand { get; } + #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged;