private void ShowDiffs(string oldText, string newText)
        {
            IDiffer differ = new Differ();

            DiffResult diffResult = differ.CreateLineDiffs(oldText, newText, false);

            ISideBySideDiffBuilder diffBuilder = new SideBySideDiffBuilder(differ);

            SideBySideDiffModel model = diffBuilder.BuildDiffModel(oldText, newText);

            this.DisplayDiffPiece(this.rtbSnapshotLeft, model.OldText.Lines, string.IsNullOrEmpty(newText));
            this.DisplayDiffPiece(this.rtbSnapshotRight, model.NewText.Lines, false);
        }
        public void Format(Document document)
        {
            if (BeautifierTagger.CurrentContentType == null || !SettingsPage.IsEnabled)
            {
                return;
            }

            var typeName = BeautifierTagger.CurrentContentType.TypeName.ToUpper();

            if (typeName != "CSS" && typeName != "SCSS")
            {
                return;
            }

            var currentDoc = dte.ActiveDocument;

            document.Activate();

            var txtDoc = document.Object() as TextDocument;

            if (txtDoc != null)
            {
                var         textManager = (IVsTextManager)Package.GetGlobalService(typeof(SVsTextManager));
                IVsTextView textView;
                textManager.GetActiveView(1, null, out textView);

                int caretLine;
                int caretCol;
                textView.GetCaretPos(out caretLine, out caretCol);

                int firstVisibleUnit;
                int ignore;
                textView.GetScrollInfo(1, out ignore, out ignore, out ignore, out firstVisibleUnit);

                var startPt = txtDoc.StartPoint.CreateEditPoint();
                var docText = startPt.GetText(txtDoc.EndPoint);

                var result = BeautifierCompiler.ProcessString(docText, BeautifierTagger.CurrentContentType);

                // ReSharper disable once BitwiseOperatorOnEnumWithoutFlags
                const int flags = (int)(vsEPReplaceTextOptions.vsEPReplaceTextTabsSpaces |
                                        vsEPReplaceTextOptions.vsEPReplaceTextNormalizeNewlines);

                if (result != docText)
                {
                    var differ     = new Differ();
                    var diffResult = differ.CreateLineDiffs(docText, result, false);

                    var beginEditPoint  = txtDoc.StartPoint.CreateEditPoint();
                    var endEditPoint    = txtDoc.StartPoint.CreateEditPoint();
                    var lineCountChange = 0;

                    txtDoc.DTE.UndoContext.Open("PostCSS Format");
                    foreach (var block in diffResult.DiffBlocks)
                    {
                        var startLine = block.DeleteStartA + lineCountChange + 1;
                        var endLine   = block.DeleteStartA + block.DeleteCountA + lineCountChange + 1;
                        lineCountChange += (block.InsertCountB - block.DeleteCountA);


                        //beginEditPoint.ReplaceText(endEditPoint, "", flags);

                        if (block.InsertCountB > 0)
                        {
                            beginEditPoint.MoveToLineAndOffset(startLine, 1);
                            endEditPoint.MoveToLineAndOffset(endLine, 1);

                            var newLines = new List <string>();
                            for (var i = 0; i < block.InsertCountB; i++)
                            {
                                var lineIndex = i + block.InsertStartB;
                                var line      = diffResult.PiecesNew[lineIndex];
                                newLines.Add(line);
                            }

                            var newText = string.Join("\r\n", newLines) + "\r\n";

                            beginEditPoint.ReplaceText(endEditPoint, newText, flags);
                        }
                        else if (block.DeleteCountA > 0)
                        {
                            beginEditPoint.MoveToLineAndOffset(startLine, 1);
                            endEditPoint.MoveToLineAndOffset(startLine + block.DeleteCountA, 1);

                            beginEditPoint.ReplaceText(endEditPoint, "", flags);
                        }
                    }
                    txtDoc.DTE.UndoContext.Close();

                    //startPt.ReplaceText(txtDoc.EndPoint, result, flags);

                    textView.SetCaretPos(caretLine, 0);
                    textView.SetScrollPosition(1, firstVisibleUnit);
                }
            }

            currentDoc.Activate();
        }
Beispiel #3
0
        public void Refresh()
        {
            this.FindControl <StackPanel>("FileContainer").Children.Clear();
            Editor editor = this.FindAncestorOfType <Editor>();

            string autosaveDirectory = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Assembly.GetEntryAssembly().GetName().Name);
            string savePath          = System.IO.Path.Combine(autosaveDirectory, editor.Guid);

            string[] files;

            try
            {
                files = System.IO.Directory.GetFiles(savePath, "*.md");
            }
            catch
            {
                files = new string[0];
            }


            long result = -1;

            List <(long, string)> sortedFiles = (from el in files let filename = System.IO.Path.GetFileNameWithoutExtension(el) where filename.StartsWith("autosave") || long.TryParse(filename, out result) let result2 = result orderby !filename.StartsWith("autosave") ? result2 : ((DateTimeOffset) new System.IO.FileInfo(el).LastWriteTimeUtc).ToUnixTimeSeconds() descending select !filename.StartsWith("autosave") ? (result2, el) : (((DateTimeOffset) new System.IO.FileInfo(el).LastWriteTimeUtc).ToUnixTimeSeconds(), el)).ToList();

            sortedFiles.Add((editor.OriginalTimeStamp, "original"));
            sortedFiles.Sort((a, b) => Math.Sign(b.Item1 - a.Item1));

            int diffWidth = (int)Math.Max(10, Math.Floor(this.Bounds.Width - 32 - 150 - 32 - 32 - 22));

            string currentText = null;
            int    lineCount   = -1;
            Differ differ      = new Differ();

            if (sortedFiles.Any())
            {
                currentText = editor.EditorControl.Text.ToString();
                lineCount   = editor.EditorControl.Text.Lines.Count;
            }

            foreach ((long timestamp, string file)file in sortedFiles)
            {
                Grid itemGrid = new Grid();

                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(32, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(150, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Star));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(36, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(1, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(36, GridUnitType.Pixel));
                itemGrid.ColumnDefinitions.Add(new ColumnDefinition(18, GridUnitType.Pixel));

                if (System.IO.Path.GetFileNameWithoutExtension(file.file).StartsWith("autosave"))
                {
                    AutosaveIcon icon = new DiagnosticIcons.AutosaveIcon();
                    ToolTip.SetTip(icon, "Autosave");
                    itemGrid.Children.Add(icon);
                }
                else if (file.file == "original")
                {
                    StartingIcon icon = new DiagnosticIcons.StartingIcon();
                    ToolTip.SetTip(icon, "Original file");
                    itemGrid.Children.Add(icon);
                }
                else
                {
                    SaveIcon icon = new DiagnosticIcons.SaveIcon();
                    ToolTip.SetTip(icon, "Manual save");
                    itemGrid.Children.Add(icon);
                }

                TextBlock timeBlock = new TextBlock()
                {
                    Text = DateTimeOffset.FromUnixTimeSeconds(file.timestamp).DateTime.ToLocalTime().ToString("HH:mm:ss \\(dd MMM\\)", System.Globalization.CultureInfo.InvariantCulture), Margin = new Thickness(5, 2, 5, 2), VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center
                };
                Grid.SetColumn(timeBlock, 2);
                itemGrid.Children.Add(timeBlock);

                DiffResult diffResult;

                if (file.file != "original")
                {
                    diffResult = differ.CreateLineDiffs(currentText, System.IO.File.ReadAllText(file.file), false);
                }
                else
                {
                    diffResult = differ.CreateLineDiffs(currentText, editor.OriginalText, false);
                }


                List <(int pos, int count, Colour colour)> diffLines = new List <(int pos, int count, Colour colour)>(from el in diffResult.DiffBlocks let pos = el.DeleteCountA > 0 ? el.DeleteStartA : el.InsertStartB orderby pos ascending select(pos, el.DeleteCountA > 0 ? el.DeleteCountA : el.InsertCountB, el.DeleteCountA > 0 ? RedColour : GreenColour));

                int currPos = 0;

                List <(double width, Colour colour)> diffBlocks = new List <(double width, Colour colour)>();

                for (int i = 0; i < diffLines.Count; i++)
                {
                    if (diffLines[i].pos > currPos)
                    {
                        diffBlocks.Add((diffLines[i].pos - currPos, GreyColour));
                        currPos = diffLines[i].pos;
                    }

                    diffBlocks.Add((diffLines[i].count, diffLines[i].colour));
                    currPos += diffLines[i].count;
                }

                if (currPos < lineCount)
                {
                    diffBlocks.Add((lineCount - currPos, GreyColour));
                    currPos = lineCount;
                }

                Page     diff = new Page(diffWidth, 20);
                Graphics gpr  = diff.Graphics;

                double currX = 0;

                for (int i = 0; i < diffBlocks.Count; i++)
                {
                    double w = diffBlocks[i].width * diffWidth / currPos;
                    gpr.FillRectangle(currX, 0, w, 20, diffBlocks[i].colour);
                    currX += w;
                }

                Viewbox diffBox = new Viewbox()
                {
                    Child = diff.PaintToCanvas(false), VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, Height = 20, Stretch = Stretch.Fill
                };
                Grid.SetColumn(diffBox, 4);
                itemGrid.Children.Add(diffBox);

                if (file.file != "original")
                {
                    Button restoreButton = new Button()
                    {
                        Content = new DiagnosticIcons.RestoreIcon(), Margin = new Thickness(3)
                    };
                    Grid.SetColumn(restoreButton, 6);
                    ToolTip.SetTip(restoreButton, "Restore");
                    itemGrid.Children.Add(restoreButton);

                    Button deleteButton = new Button()
                    {
                        Content = new DiagnosticIcons.DeleteIcon(), Margin = new Thickness(3)
                    };
                    Grid.SetColumn(deleteButton, 8);
                    ToolTip.SetTip(deleteButton, "Delete");
                    itemGrid.Children.Add(deleteButton);

                    restoreButton.Click += async(s, e) =>
                    {
                        try
                        {
                            string newText = System.IO.File.ReadAllText(file.file);
                            await editor.EditorControl.SetText(newText);

                            if (editor.EditorControl.ShowLineChanges)
                            {
                                DiffResult        diffResultFromLastSaved = editor.Differ.CreateLineDiffs(editor.LastSavedText, newText, false);
                                IEnumerable <int> changesFromLastSaved    = (from el in diffResultFromLastSaved.DiffBlocks select Enumerable.Range(el.InsertStartB, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                                DiffResult        diffResultFromOriginal = editor.Differ.CreateLineDiffs(editor.OriginalText, newText, false);
                                IEnumerable <int> changesFromOriginal    = (from el in diffResultFromOriginal.DiffBlocks select Enumerable.Range(el.InsertStartB, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                                editor.SetLineDiff(changesFromLastSaved, changesFromOriginal);
                            }
                        }
                        catch { }

                        Refresh();
                    };

                    deleteButton.Click += (s, e) =>
                    {
                        try
                        {
                            System.IO.File.Delete(file.file);
                        }
                        catch { }

                        Refresh();
                    };
                }
                else
                {
                    Button restoreButton = new Button()
                    {
                        Content = new DiagnosticIcons.RestoreIcon(), Margin = new Thickness(3)
                    };
                    Grid.SetColumn(restoreButton, 6);
                    ToolTip.SetTip(restoreButton, "Restore");
                    itemGrid.Children.Add(restoreButton);

                    restoreButton.Click += async(s, e) =>
                    {
                        string newText = editor.OriginalText;
                        await editor.EditorControl.SetText(newText);

                        if (editor.EditorControl.ShowLineChanges)
                        {
                            DiffResult        diffResultFromLastSaved = editor.Differ.CreateLineDiffs(editor.LastSavedText, newText, false);
                            IEnumerable <int> changesFromLastSaved    = (from el in diffResultFromLastSaved.DiffBlocks select Enumerable.Range(el.InsertStartB, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                            DiffResult        diffResultFromOriginal = editor.Differ.CreateLineDiffs(editor.OriginalText, newText, false);
                            IEnumerable <int> changesFromOriginal    = (from el in diffResultFromOriginal.DiffBlocks select Enumerable.Range(el.InsertStartB, Math.Max(1, el.InsertCountB))).Aggregate(Enumerable.Empty <int>(), (a, b) => a.Concat(b));

                            editor.SetLineDiff(changesFromLastSaved, changesFromOriginal);
                        }

                        Refresh();
                    };
                }

                this.FindControl <StackPanel>("FileContainer").Children.Add(itemGrid);
            }
        }