Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Monaco to load developer based files for Preview Pane #1527

Closed
barry-johnson opened this issue Mar 10, 2020 · 77 comments
Closed

Use Monaco to load developer based files for Preview Pane #1527

barry-johnson opened this issue Mar 10, 2020 · 77 comments
Assignees
Labels
Idea-New PowerToy Suggestion for a PowerToy Product-File Explorer Power Toys that touch explorer like Preview Pane Resolution-Fix Committed Fix is checked in, but it might be 3-4 weeks until a release.

Comments

@barry-johnson
Copy link

barry-johnson commented Mar 10, 2020

Summary of the new feature/enhancement

There are many plain text files which are not automatically previewed in the explorer preview pane. I think developers experience this the most given the number of source code file extensions there are.

While a previewer can be defined for them, doing so is cumbersome as it involves either direct registry edits, or my preferred powershell line:

Set-ItemProperty Registry::HKEY_CLASSES_ROOT\.ext[,.ext1,…,extN] -Name PerceivedType -Value text

A PowerToy to easily apply the text preview to a large number of file types would be convenient.

Additional option: have a pre-seeded list of the top 50-100 most common source file extensions.

Additional option: add right-click explorer menu item "Use text preview for files of this type"

Additional option (an admitted stretch): use VS Code for previewing service to allow for syntax highlighting.

@crutkas
Copy link
Member

crutkas commented Mar 10, 2020

we may be able to see if monico would be an option. issue is speed and memory footprint

@crutkas crutkas added Help Wanted We encourage anyone to jump in on these and submit a PR. Idea-New PowerToy Suggestion for a PowerToy labels Mar 10, 2020
@crutkas
Copy link
Member

crutkas commented Mar 10, 2020

Great idea leveraging the work for #914

@vhanla
Copy link
Contributor

vhanla commented Apr 15, 2020

That's a nice idea, but maybe a syntax highlighted preview handler would be even better, and optionally letting to use the explorer's text preview handler.

I was playing with the https://github.com/microsoft/PowerToys/tree/master/src/modules/previewpane PreviewHandlerCommon project and followed the instructions, then using ScintillaNET in a preview handler for source code was very easy to implement, I also tried using AvalonEdit, but both failed because they use TEMP directory and access is denied to that path, I couldn't find out why, though, maybe preview handler rules has something to do.

ScintillaNET needs to extract SciteLexer to that TEMP directory, and AvalonEdit uses that TEMP too, since it is a WPF component it requires to use ElementHost.

However, ScintillaNET allows to use a custom SciLexer.dll, so finally I could make it work.

Here a snapshot:
imagen

And my proof of concept source code is as follows:

SourceCodePreviewHandler.cs:

using System;
using System.Runtime.InteropServices;
using Common;

namespace SourceCodePreviewHandler
{
    /// <summary>
    /// Implementation of preview handler for common source code files
    /// </summary>
    [Guid("F5FD01B1-3DDE-4F68-AFD0-1E55859B0FE9")]
    [ClassInterface(ClassInterfaceType.None)]
    [ComVisible(true)]
    public class SourceCodePreviewHandler : FileBasedPreviewHandler
    {
        private SourceCodePreviewHandlerControl sourceCodePreviewHandlerControl;

        public string PreviewHandlerGUID;

        // Call common source code files rendering method here.
        public override void DoPreview()
        {
            this.sourceCodePreviewHandlerControl.DoPreview(this.FilePath);
        }

        protected override IPreviewHandlerControl CreatePreviewHandlerControl()
        {

            this.sourceCodePreviewHandlerControl = new SourceCodePreviewHandlerControl();
            this.sourceCodePreviewHandlerControl.PreviewHandlerGUID = this.GetType().GUID.ToString().ToUpper();
            return this.sourceCodePreviewHandlerControl;
        }
    }
}

SourceCodePreviewHandlerControl.cs:

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Forms.Integration;
using Common;
using Microsoft.Win32;
using ScintillaNET;

namespace SourceCodePreviewHandler
{
    public class SourceCodePreviewHandlerControl : FormHandlerControl
    {

        private Scintilla textArea;

        public string PreviewHandlerGUID;

        public SourceCodePreviewHandlerControl()
        {
            // initialization
        }

        public override void DoPreview<T>(T dataSource)
        {
            this.InvokeOnControlThread(() =>
            {
                try
                {
                    // get SciLexer Dynamic Link Library path, must be in preview handler's path
                    string SciLexerPath = (string)Registry.GetValue(@"HKEY_CLASSES_ROOT\CLSID\{"+PreviewHandlerGUID+@"}\InprocServer32", "CodeBase", null);
                    SciLexerPath = Path.GetDirectoryName(SciLexerPath.Replace(@"file:///", ""));

                    if (Environment.Is64BitProcess)
                    {
                        SciLexerPath += @"\SciLexer.x64.dll";
                    }
                    else
                    {
                        SciLexerPath += @"\SciLexer.x86.dll";
                    }

                    // ScintillaNET embeds SciLexer.dll and extracts it to TEMP folder, but preview handler somehow access is denied
                    Scintilla.SetModulePath(SciLexerPath);

                    string filePath = dataSource as string;
                    string fileText = File.ReadAllText(filePath);

                    this.textArea = new Scintilla
                    {
                        Dock = DockStyle.Fill,
                        WrapMode = WrapMode.None,
                        IndentationGuides = IndentView.LookBoth
                    };

                    this.textArea.Margins[0].Width = 0;

                    this.textArea.StyleResetDefault();
                    this.textArea.Styles[Style.Default].Font = "Consolas";
                    this.textArea.Styles[Style.Default].Size = 10;
                    this.textArea.StyleClearAll();
                    // Configure the CPP (C#) lexer styles
                    this.textArea.Styles[Style.Cpp.Default].ForeColor = Color.Silver;
                    this.textArea.Styles[Style.Cpp.Comment].ForeColor = Color.FromArgb(0, 128, 0); // Green
                    this.textArea.Styles[Style.Cpp.CommentLine].ForeColor = Color.FromArgb(0, 128, 0); // Green
                    this.textArea.Styles[Style.Cpp.CommentLineDoc].ForeColor = Color.FromArgb(128, 128, 128); // Gray
                    this.textArea.Styles[Style.Cpp.Number].ForeColor = Color.Olive;
                    this.textArea.Styles[Style.Cpp.Word].ForeColor = Color.Blue;
                    this.textArea.Styles[Style.Cpp.Word2].ForeColor = Color.Blue;
                    this.textArea.Styles[Style.Cpp.String].ForeColor = Color.FromArgb(163, 21, 21); // Red
                    this.textArea.Styles[Style.Cpp.Character].ForeColor = Color.FromArgb(163, 21, 21); // Red
                    this.textArea.Styles[Style.Cpp.Verbatim].ForeColor = Color.FromArgb(163, 21, 21); // Red
                    this.textArea.Styles[Style.Cpp.StringEol].BackColor = Color.Pink;
                    this.textArea.Styles[Style.Cpp.Operator].ForeColor = Color.Purple;
                    this.textArea.Styles[Style.Cpp.Preprocessor].ForeColor = Color.Maroon;
                    this.textArea.Lexer = Lexer.Cpp;
                    this.textArea.ReadOnly = false;
                    this.textArea.Text = fileText;
                    this.textArea.ReadOnly = true;

                    // disable context menu because it steals focus, and makes explorer file navigation loses focus
                    this.textArea.ContextMenu = new ContextMenu();

                    this.Controls.Clear();
                    this.Controls.Add(textArea);
                    base.DoPreview(dataSource);
                }
                catch (Exception e)
                {
                    MessageBox.Show(e.Message);
                    base.DoPreview(dataSource);
                }
            });
        }
        
    }
}

However, there is more room for improvements, like detection of appropriate lexer for the selected file, it could be great to allow choosing which source code files to highlight from the settings window in PowerToys, themes, and detection of explorer's dark mode.

@barry-johnson
Copy link
Author

Thanks for the PoC - impressive to see something working. Yes, syntax highlighting was indeed the ideal stretch goal for this feature. The idea of incorporating themes & dark mode would be very nice elements! From browsing the source on the SVG viewer, I see that it just uses a browser extension to do this, hence I think the idea from @crutkas of using the Monaco editor which power VS Code, which would open up the ability to use installed VS Code themes as an option. Thanks!

@crutkas crutkas added this to the Suggested Ideas milestone Jun 11, 2020
@crutkas crutkas changed the title PowerToy to easily associate filetypes with text preview Use Monaco to load developer based files for Preview Pane Jul 20, 2020
@crutkas
Copy link
Member

crutkas commented Jul 20, 2020

https://github.com/microsoft/monaco-editor could be a solid implementation item

@robertdumitrescu
Copy link

This would streamline the work for so many developers and technical centric roles. Huge supporter of this. Might be able to help with the implementation but I only know JS.

@crutkas
Copy link
Member

crutkas commented Dec 8, 2020

I think some simple WPF / WinForm concept with buttons that flip known formats would be helpful.

@michael-hawker did you say you had a control we may be able to base this off of?

@michael-hawker
Copy link

🦙 Yup, I have a C# UWP Projection of the Monaco Editor (hosted via WebView) that I did as a side project: https://github.com/hawkerm/monaco-editor-uwp. It should provide basic text highlighting for many languages out of the box (just as Monaco does as it's the same 🙂).

It's been on my backlog to ship some fixes I did earlier this year, but they're all focused for editor builders. The control is the same one we use in the Toolkit Sample App and my XAML Studio Garage project, so it's been pretty stable. I'm in the process of figuring out if we pull this wrapper into the Toolkit more officially though, but I'm trying to sync with the Monaco folks first before we do.

@michael-hawker
Copy link

Ah, thinking if this needs to be for WPF instead of UWP. Alex has a branch using WebView2 (for WinUI 3) and the Uno folks have started splitting the project a bit to support different platforms in their fork here.

If we move the C# typings to a .NET Standard project, we should get closer to being able to use the WebView2 version from UWP but on top of the .NET WebView2 that'll work for WPF. Assuming the Monaco is good with broadening the audience for the language projection, I'm happy to help facilitate figuring out moving the project forward. (It'd be easier that way to add Blazor support too to centralize efforts on top of the C# language projection bits we already auto-generate).

@Aaron-Junker
Copy link
Collaborator

As a feature suggestion on this:
It would be great if it is possible for the user to config the syntax highlighting style. (Like vscode, visual studio, sublime text, JetBrains..... ) 😄

Also got this request on twitter. But I think this is a feature for future releases.

@franky920920
Copy link
Contributor

Also got this request on twitter. But I think this is a feature for future releases.

Agree, just making sure we have this logged. :D

@gen3vra
Copy link

gen3vra commented Dec 7, 2021

This looks great, I'm really excited for this :D

@crutkas
Copy link
Member

crutkas commented Dec 7, 2021

Chances are 55 for our team. 53 I think is pretty full at this point.

@crutkas crutkas added this to To do in 0.55 Release via automation Dec 7, 2021
@ghost
Copy link

ghost commented Dec 7, 2021

Also very happy about how this replaced microsoft/vscode#73771.

@azhe403
Copy link

azhe403 commented Dec 8, 2021

It's will be great because no longer use notepad/Code for just view content

@Aaron-Junker
Copy link
Collaborator

This will help us a lot: MicrosoftEdge/WebView2Announcements#37

@crutkas crutkas moved this from In progress to Done in 0.55 Release Jan 26, 2022
@crutkas crutkas added Resolution-Fix Committed Fix is checked in, but it might be 3-4 weeks until a release. and removed Status-In progress This issue or work-item is under development labels Jan 26, 2022
@vklachkov
Copy link

Offtop
Many years ago I wrote a similar project. I didn't think that such a feature would be useful to anyone. And here already in powertoys they implement :)

@crutkas
Copy link
Member

crutkas commented Jan 31, 2022

@zgdump if you think you need something. Chances are others do too :)

@vklachkov
Copy link

vklachkov commented Jan 31, 2022

@crutkas yeah, but only the persistent ones bring it to production, show it to people. I gave up)

@Aaron-Junker
Copy link
Collaborator

@zgdump if you have any other projects that you think could be useful for others, then let us now!

@Aaron-Junker
Copy link
Collaborator

@zgdump if you have any other projects that you think could be useful for others, then let us know!

@vklachkov
Copy link

@Aaron-Junker no, I stopped writing projects for Windows a long time ago. The last thing I support is the virtual desktop indicator. A trifle, but necessary. Too insignificant for powertoys)

@crutkas
Copy link
Member

crutkas commented Jan 31, 2022

The was fixed in in 0.55. Head over to https://aka.ms/installpowertoys to try it out

@crutkas crutkas closed this as completed Jan 31, 2022
@GarThor
Copy link

GarThor commented May 23, 2023

This says it's completed, however I don't see a way to add a known extension to the tool with or without syntax highlighting?

Am I missing something?

@htcfreek
Copy link
Collaborator

@GarThor
You can't add new extensions using a setting or changing a json file on your computer.

Adding new extensions requires code changes. You can either open a new issue to suggest the new file type/extension or you can open PR for the required code changes.

@GarThor
Copy link

GarThor commented May 23, 2023

@htcfreek

I figured it out, using the original poster's registry hack. Though, it'd be nice to be able to do this without having to hack the registry... but also, it'd be nice if I could associate the extension with an existing/custom syntax highlighting schema.

I'm dealing with a proprietary text format, so I feel it wouldn't be appropriate to ask the powertoys team to implement the particular filetype extension/syntax highlighting I need... however having the ability to customize it would be a nice to have for future releases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Idea-New PowerToy Suggestion for a PowerToy Product-File Explorer Power Toys that touch explorer like Preview Pane Resolution-Fix Committed Fix is checked in, but it might be 3-4 weeks until a release.
Projects
No open projects
Development

No branches or pull requests