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

API to hide parts of the code #45

Open
AchimKO opened this issue Jul 1, 2016 · 31 comments
Open

API to hide parts of the code #45

AchimKO opened this issue Jul 1, 2016 · 31 comments
Labels
editor-core feature-request Request for new features or functionality
Milestone

Comments

@AchimKO
Copy link

AchimKO commented Jul 1, 2016

Hi,

we use the monaco editor for a project and we need to hide some parts of the code from the user, because there is a Header and a Footer generated, and only a part between which should be editable by the user. We need the whole file in the background, to have a running code completion.

export class GeneratedClass {
     public GeneratedProperty1: string;
     public GeneratedProperty2: string;

    construcor() {}

    // User Code starts here
    public Property1ByUser: string;
    public Property2ByUser: srting;

    public MethodByUser() {}
    // User Code ends here
}

The user should only be able to edit the code between the two comments.
Is it possible to hide the other parts from the user, or disable them in any way?

Thanks,

Achim

@alexdima
Copy link
Member

Sorry for the late reply, there is a non-API way (might get removed in the future):
editor.getMode().setEditableRange(myRange).

interface IModel {
...
    /**
     * Set an editable range on the model.
     * @internal
     */
    setEditableRange(range:IRange): void;
...
}

@alexdima alexdima added the feature-request Request for new features or functionality label Aug 15, 2016
@AchimKO
Copy link
Author

AchimKO commented Aug 16, 2016

Thank you,
this helps a lot.

In addition i solved to hide parts of the code by calling:

editor.setHiddenArea(myRange)

But for that to work I had to overwrite the FoldingController, it also handles the hidden Areas and was overriding mine.

Would be great to have a build in way to hide Areas in combination with the Folding controller.

@alexdima
Copy link
Member

👍 we plan at one point to make setHiddenArea more cooperative. Today the FoldingController thinks it owns those.

@devdoomari
Copy link

any update on this issue?
I'm making a 'code-playground' and I'd really like to have monaco hide some import statements.
(I couldn't get typescript to 'globalize' modules)

@alexdima alexdima modified the milestone: Backlog Jun 7, 2017
@rizrmd
Copy link

rizrmd commented Dec 21, 2017

Any update on this issue ?

@yaananth
Copy link
Member

now it's called setHiddenAreas however it doesn't honor the startColumn or endColumn :(
So it hides whole lines! Can we add support to hide specific columns please!

@yaananth
Copy link
Member

yaananth commented Jul 19, 2018

Never mind, I can do this :)

const matches = contentModel.findMatches("someregex", false, true, false, null, true);
 contentModel.applyEdits(matches.map(x => {
                    return {
                        text: "",
                        range: x.range
                    }
                }));

However, the use case is that I would need to is to colorize using monaco.editor.ITokenThemeRule[] and then strip the things out. As soon as I strip them out, the line renders again and hence the colors are gone ... :(

@benhutchison
Copy link

I noticed that, although being a user feature request, setEditableRange seems to be removed from vscode as "unused code" as part of this issue

Please consider re-including a setEditableRange into the supported API.

It is useful in education and/or alongside code-generation; use cases where the user isn't intended to edit all of the source file.

@mw-ding
Copy link

mw-ding commented Aug 27, 2018

+1 on including setEditableRange and setHiddenAreas.

@jansivans
Copy link

If you are using typescript, you can use

monaco.languages.typescript.typescriptDefaults.addExtraLib('const arr = [];')

to achieve similar effect. Now arr variable will appear in intellisense.

@VitalickS
Copy link

VitalickS commented Mar 27, 2019

If you are using typescript, you can use

monaco.languages.typescript.typescriptDefaults.addExtraLib('const arr = [];')

to achieve similar effect. Now arr variable will appear in intellisense.

And it is better use like this

import Space, { env as EnvClass } from 'vpt';

declare global {
    const space: Space;
    const env: typeof EnvClass;
}

@raghav-g
Copy link

raghav-g commented Jun 3, 2019

Can we hide parts of the code instead of folding it or making it read only?

@boydc2014
Copy link

Any update on this one ?

@datou0412
Copy link
Contributor

Any update?

@CosmoMyzrailGorynych
Copy link

So I made a solution, at least for some cases. I've made the first and last line uneditable.

If what you want to achieve is doable with addExtraLib, do use it. This is a nice official way to add typings and stuff. My solution handles the case where it was not enough, mainly to change the context of functions (change to what this points).

For my game editor ct.js, I ended up with tons of hacks that establish hidden and uneditable lines around the code: https://github.com/ct-js/ct-js/blob/develop/src/js/codeEditorHelpers.js#L74
Beware: it uses several unofficial APIs and this is not a solution to the original issue, but a collection of hacks due to the absence of better alternatives.

The hacks block direct editing from a keyboard, manage cursors and selectors, handle "Replace all" command, and hide the first and the last lines. Some constants are hard-coded, so you will need to improve the code for multiple hidden lines. The known issue is that you can view and delete the hidden code in the peek view, as it creates additional editors.

@alexdima alexdima changed the title hide parts of the code API to hide parts of the code Dec 10, 2019
@alexdima alexdima modified the milestones: Backlog, Backlog Candidates Dec 10, 2019
@mehulmpt
Copy link

mehulmpt commented Feb 9, 2020

Is there any update on this API? Or any available workarounds to disable a bunch of lines for editing in monaco?

@hems
Copy link

hems commented May 1, 2020

I have the same requirement, where ideally I would have a few lines hidden before and after the user code, this way the user wouldn't have to worry about boilerplate code and at the same time VSCode would still validate the code as if the boilerplate was wrapping the user code.

For instance on my case i would like the user to edit:

myEvent: (data) => { 
  //  do something 
},
anotherEvent: (data) => { 
  //  do something 
},

And before validating I would like to wrap it all in events = { ${code} } basically making a simplification for my user to edit a javascript object.

@mauricedoepke
Copy link

Would be greatt for my case, too. I would like the user to write code that contains the await keyword without exposing him to the async function around. So basically I would like to wrap the user code inside this:

(async () => {
 //user code goes here
})()

Without exposing this wrapper function to my user.

@axefrog
Copy link

axefrog commented Sep 4, 2020

I need this functionality also. I'm currently working out a way to approximate the behaviour perhaps by intercepting and cancelling edits in "read only" ranges.

Ideas:

  • onDidChangeCursorPosition and onDidChangeCursorSelection, then force the cursor away from read-only ranges
  • deltaDecorations to make read-only appear in grey
  • Toggle read-only mode based on whether editing is currently permitted: editor.updateOptions({ readOnly: true|false })

Edit: Added third idea above

@Pranomvignesh
Copy link
Contributor

Ideas:

  • onDidChangeCursorPosition and onDidChangeCursorSelection, then force the cursor away from read-only ranges
  • deltaDecorations to make read-only appear in grey

I would like to add one more idea, if we undo the values entered in the areas which we marked as read-only, then user wont feel like that area is editable, and we can show it as a boilerplate code for the users
Actually i tried implementing this idea and for me it is working pretty well.
If you are interested to see the demo please check this link
If anyone wants to know more about the implementation read this article
For the code , see the github repo

@quantumsheep
Copy link

Any update on this?

@RickeyWard
Copy link

The internal ICodeEditor.setHiddenAreas(IRange[]) works well for this. It's an internal API but its used heavily in the newer notebooks stuff, so I'm willing to take the risk. I'm using the editor to view logs, and I wanted to be able to filter them in a way that hides anything that doesn't match and it works well.

editor.setHiddenAreas([]) will show them again, and editor.setHiddenAreas([new Range(1,0,10,0), new Range(20,0,30,0)]); will hide the first 10 and last 10 of a 30 line file. Line numbers stay correct for the areas shown.

I'd like to propose to maintainers that this api become public, this is a useful feature.

@hongping
Copy link

hongping commented Jun 9, 2021

The internal ICodeEditor.setHiddenAreas(IRange[]) works well for this. It's an internal API but its used heavily in the newer notebooks stuff, so I'm willing to take the risk. I'm using the editor to view logs, and I wanted to be able to filter them in a way that hides anything that doesn't match and it works well.

editor.setHiddenAreas([]) will show them again, and editor.setHiddenAreas([new Range(1,0,10,0), new Range(20,0,30,0)]); will hide the first 10 and last 10 of a 30 line file. Line numbers stay correct for the areas shown.

I'd like to propose to maintainers that this api become public, this is a useful feature.

How do you expose the API?

@akutruff
Copy link

Looking for this as well.

arlosi pushed a commit to arlosi/monaco-editor that referenced this issue Oct 29, 2021
[clojure] Improve Clojure syntax highlighting.
alexdima added a commit that referenced this issue Nov 5, 2021
@kristofer84
Copy link

How do you expose the API?

One way is to extend the interface and then cast your instance to that interface and call the method:

interface IMyStandaloneCodeEditor extends monaco.editor.IStandaloneCodeEditor {
  setHiddenAreas(range: monaco.IRange[]): void;
}

...

const casted = editor as IMyStandaloneCodeEditor;
const range = new monaco.Range(1, 0, 1, 0);
casted.setHiddenAreas([range]);

@Gbahdeyboh
Copy link

Hi @alexdima.

It looks like setEditableRange and setHiddenAreas are no longer a part of the API. I would really appreciate it if you could suggest a workaround for this if you're aware of any.

@RickeyWard
Copy link

It looks like setEditableRange and setHiddenAreas are no longer a part of the API. I would really appreciate it if you could suggest a workaround for this if you're aware of any.

setHiddenAreas still seems to be there, but setEditableRange does appear to be gone.
Current vscode/main/src/vs/editor/editorBrowser.ts
image

it will appear as though its not there, you just have to @ts-ignore or cast to any when using it in ts (editor as any).setHiddenAreas(...) you won't get any code completion for it, but it will work.

The current published version 0.34.1 this still works. here it is in the playground
image

@Gbahdeyboh
Copy link

Thanks, @RickeyWard. I've been doing it wrong. I was trying to .setHiddenAreas on a model instance.

The editor I'm trying to modify its values is not created by me, I am making use of window.editor to get the model instance. I've snooped around and can't seem to find an elegant way of getting the current editor's instance since I'm not creating the editor myself and window.editor.setHiddenAreas() wouldn't work. Is there a way to navigate around that?

@RickeyWard
Copy link

The editor I'm trying to modify its values is not created by me, I am making use of window.editor to get the model instance. I've snooped around and can't seem to find an elegant way of getting the current editor's instance since I'm not creating the editor myself and window.editor.setHiddenAreas() wouldn't work. Is there a way to navigate around that?

@Gbahdeyboh monaco.editor.getEditors() returns an array of editor instances, if you have access to the global monaco object you can get access to the editor instance I'm guessing window.editor is that but I'm not sure. If you're not driving monaco, then the more advanced things you try to do the harder it's going to be. GL!

@Ginxo
Copy link

Ginxo commented Sep 25, 2024

In case of using setHiddenAreas content still searchable... is there a way to also limit searching for visible areas?
In case I use something like

      (editor as any).setHiddenAreas([new Range(1, 0, 1, 0), new Range(4, 0, 4, 0), new Range(8, 0, 8, 0)]);

content from lines 1, 4, 8 still searchable 🤔

Many thanks!

@CosmoMyzrailGorynych
Copy link

CosmoMyzrailGorynych commented Oct 5, 2024

All this is useless shit as there are tons of drawbacks besides just search issues and content being editable outside of the currently visible lines.

A fresh approach I've discovered is inspired by Civet's VSCode extension, basically you create a custom language that uses TS tokenizer, and steals QuickInfo, model markers, and completions from a regular TS Model that has your wrappers added, and you adjust positions according to your wrappers.

This loses Ctrl+Click discoverability across files, but is fine in my case. (A game engine.) Inline error checks, documentation and completions are all working.

I don't have a ready-made example for TypeScript yet, but I do have a working implementation of Civet language in Monaco, with custom wrappers for function descriptor and additional local variables. A seeking mind will be able to simplify it back to be just TypeScript but with wrappers. Civet compiles to TypeScript so I additionally use sourcemaps to go from TypeScript back to user's Civet code.

A working HoverProvider

Diagnostic transfer

HoverProvider, diagnostics conversion, and completions converter: https://github.com/ct-js/ct-js/blob/16e926544192ce334953e1fdbefe119a7f6ab194/src/node_requires/civetLanguageFeatures.ts
MIT license, partially based on Civet's LSP code. (MIT as well)

I then use this to init the language features:

const coffeescriptTokenizer = require('src/node_requires/coffeescriptTokenizer.js').language;
const {CivetHoverProvider, completionsProvider, provideMarkers} = require('src/node_requires/civetLanguageFeatures.ts/');

const ts = monaco.languages.typescript;

monaco.languages.register({
    id: 'civet'
});

// Workaround for an ancient bug that ignores custom providers
monaco.editor.create(document.createElement('textarea'), {
    language: 'civet',
    value: ':)'
});
setTimeout(() => {
    monaco.languages.setMonarchTokensProvider('civet', coffeescriptTokenizer);
    monaco.languages.registerCompletionItemProvider('civet', completionsProvider);
    ts.getTypeScriptWorker()
    .then(client => {
        monaco.languages.registerHoverProvider('civet', new CivetHoverProvider(client));
    });
}, 1000);

And on your custom languages' editors, call provideMarkers(codeEditor); to retrieve diagnostics markers (these are errors and warnings in code).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
editor-core feature-request Request for new features or functionality
Projects
None yet
Development

No branches or pull requests