Пример #1
0
        public FileTailerViewModel(ILogger logger,ISchedulerProvider schedulerProvider, FileInfo fileInfo)
        {
            if (logger == null) throw new ArgumentNullException(nameof(logger));
            if (schedulerProvider == null) throw new ArgumentNullException(nameof(schedulerProvider));
            if (fileInfo == null) throw new ArgumentNullException(nameof(fileInfo));

            var filterRequest = this.WhenValueChanged(vm => vm.SearchText).Throttle(TimeSpan.FromMilliseconds(125));
            var autoChanged = this.WhenValueChanged(vm => vm.AutoTail);
            var scroller = _userScrollRequested
                        .CombineLatest(autoChanged, (user, auto) =>
                        {
                            var mode = AutoTail ? ScrollingMode.Tail : ScrollingMode.User;
                            return  new ScrollRequest(mode, user.PageSize, user.FirstIndex);
                        })
                        .Sample(TimeSpan.FromMilliseconds(150))
                        .DistinctUntilChanged();

            var tailer = new FileTailer(fileInfo, filterRequest, scroller);

            //create user display for count line count
            var lineCounter = tailer.TotalLines.CombineLatest(tailer.MatchedLines,(total,matched)=>
            {
                return total == matched
                    ? $"File has {total.ToString("#,###")} lines"
                    : $"Showing {matched.ToString("#,###")} of {total.ToString("#,###")} lines";
            })
            .Subscribe(text => LineCountText=text);

            //load lines into observable collection
            var loader = tailer.Lines.Connect()
                .Transform(line => new LineProxy(line))
                .Sort(SortExpressionComparer<LineProxy>.Ascending(proxy => proxy.Number))
                .ObserveOn(schedulerProvider.MainThread)
                .Bind(out _data)
                .Subscribe(changes => logger.Info($"Rows changed {changes.Adds} adds, {changes.Removes} removed"),
                            ex => logger.Error(ex, "There is a problem with bind data"));

            //monitor matching lines and start index,
            var matchedLinesMonitor = tailer.MatchedLines
                .Subscribe(matched => MatchedLineCount = matched);

            //track first visible index
            var firstIndexMonitor = tailer.Lines.Connect()
                .QueryWhenChanged(lines =>lines.Count == 0 ? 0 : lines.Select(l => l.Index).Min())
                .Subscribe(first=> FirstIndex= first);

            _cleanUp = new CompositeDisposable(tailer,
                lineCounter,
                loader,
                firstIndexMonitor,
                matchedLinesMonitor,
                Disposable.Create(() =>
                {
                    _userScrollRequested.OnCompleted();
                }));
        }
Пример #2
0
        public void AutoTailWithFilter()
        {
            var file = Path.GetTempFileName();
            var info = new FileInfo(file);
            var scheduler = new TestScheduler();
            var textMatch = Observable.Return("odd");
            var autoTailer = Observable.Return(new ScrollRequest(10));

            File.AppendAllLines(file, Enumerable.Range(1, 100)
                .Select(i => i%2 == 1 ? $"{i} is an odd number" : $"{i} is an even number").ToArray());

            using (var tailer = new FileTailer(info, textMatch, autoTailer, scheduler))
            {

                //lines which contain "1"
                var expectedLines = Enumerable.Range(1, 100)
                    .Select(i => i % 2 == 1 ? $"{i} is an odd number" : $"{i} is an even number")
                    .Where(s => s.Contains("odd"))
                    .Reverse()
                    .Take(10)
                    .Reverse()
                    .ToArray();

                scheduler.AdvanceBySeconds(1);

                tailer.Lines.Items.Select(l => l.Text).ShouldAllBeEquivalentTo(expectedLines);

                File.AppendAllLines(file, Enumerable.Range(101, 10)
                .Select(i => i % 2 == 1 ? $"{i} is an odd number" : $"{i} is an even number").ToArray());

                scheduler.AdvanceBySeconds(1);

                expectedLines = Enumerable.Range(1, 110)
                    .Select(i => i % 2 == 1 ? $"{i} is an odd number" : $"{i} is an even number")
                    .Where(s => s.Contains("odd"))
                    .Reverse()
                    .Take(10)
                    .Reverse()
                    .ToArray();

                scheduler.AdvanceBySeconds(1);

                File.Delete(file);
                tailer.Lines.Items.Select(l => l.Text).ShouldAllBeEquivalentTo(expectedLines);
            }
        }
Пример #3
0
        public void AutoTailWithFilter()
        {
            var scheduler = new TestScheduler();
            var autoTailer = Observable.Return(new ScrollRequest(10));

            Func<string, bool> predicate = s => s.Contains("odd");
            using (var file = new TestFile())
            {

                file.Append(Enumerable.Range(1, 100).Select(i => i%2 == 1 ? $"{i} is an odd number" : $"{i} is an even number").ToArray());
                var search = file.Info.Search(predicate,  scheduler);

                using (var tailer = new FileTailer(file.Info, search, autoTailer, new NullLogger(), scheduler))
                {

                    //lines which contain "1"
                    var expectedLines = Enumerable.Range(1, 100)
                        .Select(i => i%2 == 1 ? $"{i} is an odd number" : $"{i} is an even number")
                        .Where(s => s.Contains("odd"))
                        .Reverse()
                        .Take(10)
                        .Reverse()
                        .ToArray();

                    scheduler.AdvanceBySeconds(1);

                    tailer.Lines.Items.Select(l => l.Text).ShouldAllBeEquivalentTo(expectedLines);

                    file.Append( Enumerable.Range(101, 10).Select(i => i%2 == 1 ? $"{i} is an odd number" : $"{i} is an even number").ToArray());

                    scheduler.AdvanceBySeconds(1);

                    expectedLines = Enumerable.Range(1, 110)
                        .Select(i => i%2 == 1 ? $"{i} is an odd number" : $"{i} is an even number")
                        .Where(s => s.Contains("odd"))
                        .Reverse()
                        .Take(10)
                        .Reverse()
                        .ToArray();

                    scheduler.AdvanceBySeconds(1);

                    tailer.Lines.Items.Select(l => l.Text).ShouldAllBeEquivalentTo(expectedLines);
                }
            }
        }
Пример #4
0
        public void AutoTail()
        {
            var file = Path.GetTempFileName();
            var info = new FileInfo(file);
            var scheduler  = new TestScheduler();
            var textMatch = Observable.Return((string)null);
            var autoTailer = Observable.Return(new ScrollRequest(10));

            File.AppendAllLines(file, Enumerable.Range(1, 100).Select(i =>i.ToString()).ToArray());

            using (var tailer = new FileTailer(info, textMatch, autoTailer,scheduler))
            {

                tailer.Lines.Items.Select(l => l.Number).ShouldAllBeEquivalentTo(Enumerable.Range(91, 10));
                File.AppendAllLines(file, Enumerable.Range(101, 10).Select(i => i.ToString()));

                scheduler.AdvanceByMilliSeconds(250);
                File.Delete(file);
                tailer.Lines.Items.Select(l => l.Number).ShouldAllBeEquivalentTo(Enumerable.Range(101, 10));
            }
        }
Пример #5
0
        public void AutoTail()
        {
            var scheduler  = new TestScheduler();
            var textMatch = Observable.Return(FileSearchResult.None);
            var autoTailer = Observable.Return(new ScrollRequest(10));

            using (var file = new TestFile())
            {
                file.Append( Enumerable.Range(1, 100).Select(i => i.ToString()).ToArray());

                using (var tailer = new FileTailer(file.Info, textMatch, autoTailer, new NullLogger(), scheduler))
                {
                    scheduler.AdvanceByMilliSeconds(250);
                    tailer.Lines.Items.Select(l => l.Number).ShouldAllBeEquivalentTo(Enumerable.Range(91, 10));
                    file.Append( Enumerable.Range(101, 10).Select(i => i.ToString()));

                    scheduler.AdvanceByMilliSeconds(250);
                    tailer.Lines.Items.Select(l => l.Number).ShouldAllBeEquivalentTo(Enumerable.Range(101, 10));
                }
            }
        }
Пример #6
0
        public void WillNotApplyFilterWhenTextIsLessThan3Character()
        {
            var file = Path.GetTempFileName();
            var info = new FileInfo(file);
            var scheduler = new TestScheduler();
            var textMatch = Observable.Return((string)"1");
            var autoTailer = Observable.Return(new ScrollRequest(10));

            File.AppendAllLines(file, Enumerable.Range(1, 100).Select(i => i.ToString()).ToArray());

            using (var tailer = new FileTailer(info, textMatch, autoTailer, scheduler))
            {

                //lines which contain "1"
                int[] expectedLines = Enumerable.Range(91, 10)
                    .Select(i => i.ToString())
                    .Select(int.Parse)
                    .ToArray();

                scheduler.AdvanceBySeconds(1);

                tailer.Lines.Items.Select(l => l.Number).ShouldAllBeEquivalentTo(expectedLines);

                File.Delete(file);
                tailer.Lines.Items.Select(l => l.Number).ShouldAllBeEquivalentTo(expectedLines);
            }
        }