Theia: Open Theia to a specific folder?

Created on 27 Feb 2018  ·  45Comments  ·  Source: eclipse-theia/theia

Is there a way through the browser to get Theia to open to a specific folder under the workspace (i.e. by specifying the folder name as part of the URL used to access Theia)?

question

All 45 comments

I know for sure you can't use the url to access different workspaces, or did I misunderstand the question?

Not looking to access different workspaces, but looking to have Theia expand the left tree to a specified folder under the workspace, or to edit a specified file.

No, it is not possible right now. You can implement a custom extension for your cases which does it.

I am trying to write an extension for this... but first show stopper is, how to import workspaceservices?

I added this to my extension's package.json:

“dependencies”: {
   “@theia/core”: “^0.3.7”,
   “@theia/workspace”: “^0.3.7”
 },

and have this in my extension code:

import { WorkspaceService } from ‘@theia/workspace/browser/lib/workspace-service’;

but it did not work:

src/browser/demo-contribution.ts(2,34): error TS2307: Cannot find module '@theia/workspace/browser/lib/workspace-service'.

How can I correctly import it?

@travis1111 Hi, have you run yarn to download new packages?

Yes I did. this is from log

$ yarn run clean && yarn run build
yarn run v1.5.1
warning package.json: No license field
$ rimraf lib
Done in 0.18s.
yarn run v1.5.1
warning package.json: No license field
$ tsc
src/browser/demo-contribution.ts(2,34): error TS2307: Cannot find module '@theia/workspace/browser/lib/workspace-service'.

Could you share your project on GH?

ok let me do it

Here It should be

import { WorkspaceService } from '@theia/workspace/lib/browser/workspace-service'; instead of
import { WorkspaceService } from '@theia/workspace/browser/lib/workspace-service';

Small typo I think :)

Thanks! now I can close the editor now :-)

any suggestion on what is the next step? how to pass in parameters (path to open) to extension, I guess if I receive the path, it's a matter of construct a URI and use workspace.open(uri)?

@epatpol do you know how to get query parameter in my extension? then how to let theia to open that folder by default? so something like before the editor is opened I set the folder to be the value I passed in so that theia can open the new workspace folder...

@travis1111 I don't really know how all the routing currently works in the application, but I think you could maybe start looking into BackendApplicationContribution. For instance, the @theia/metrics extension adds a route to metrics which fetches node information.

In your case maybe you could add a contribution that checks for any route (I don't know how to do it in Express sorry), get that string, make sure it actually maps to a folder on the FS and if so, use the workspace extension to open this one.

Does that answer your question?

yes, it helps :-) let me take a look of that extension. Thank you

No problem! I've edited my message as somehow the @theia/metrics wasn't rendered properly

thanks!!

So l looked at the code (metrics extension), I think one way to do it is ...

similar to metrics extension, expose a GET endpoint, query param contains the workspace root, so in the extension code, I set the server root to be the specified root, then from frontend code do a refresh of current browser window... am I on the right track?

I tried to see how metrics extension works, but /metrics returns this

Cannot GET /metrics

Suggestions?

@travis1111 I would say that yes you're definitely on the right track :)

As for the metrics extension not working, I can have a look tomorrow if you want.

sure please :-)

I am very new to Theia, so could be something wrong from my side :)

thanks a lot!!!

@travis1111 It seems to still work for me fetching localhost:3000/metrics when running the browser example with the metrics extension, are you sure you added the @theia/metrics extension to your application's package.json ?

Thanks! Yeah I forgot to add it. So I added @theia/metrics in the json, and it worked, I can GET the endpoint,

So my extension was created based on it, but if I include my extension in the build, the build is ok, but editor won't launch (failed to connect). here is my extension

https://github.com/travis1111/theia-extension/tree/master/

Do you mind take a look?

Thanks

@travis1111 Did you forget to commit some changes to https://github.com/travis1111/theia-extension/blob/master/switch-ws-extension/src/node/switchws-backend-contribution.ts in master? I can't test it right now as it is as there are compilation errors (undefined rootUri for instance).

Thanks, that was for testing, I just updated the code to use "/home".

I think you need to bind SwitchWSBackendContribution to something, in this case to itself no?

https://github.com/travis1111/theia-extension/blob/master/switch-ws-extension/src/node/switchws-backend-module.ts#L8

bind(SwitchWSBackendContribution).toSelf().inSingletonScope();

I changed to this

bind(SwitchWSBackendContribution).toSelf().inSingletonScope();

but still not working.

Sorry I am really new to this so don't know why I need to or why I don't need to, I just copied metrics extension, and removed code I do not need and added code I need :-)

Metrics extension did not bind to itself and it is working :-(

You're right you shouldn't have to do this my bad. How are you developing your extension relative to the theia project. Cloning your project I can't seem to be able to compile your contributions. You have a sample app (sample package.json ) using your extension?

We build it in a Docker container, this is snippet of the Docker:

COPY switch-ws-extension /home/theia/switch-ws-extension
RUN cd switch-ws-extension \
  && yarn \
  && rm -fr node_modules \
  && yarn cache clean \
  && cd ..

and the sample app:

{
    "private": true,
    "dependencies": {
        "@theia/typescript": "^0.3.7",
        "@theia/navigator": "^0.3.7",
        "@theia/terminal": "^0.3.7",
        "@theia/outline-view": "^0.3.7",
        "@theia/preferences": "^0.3.7",
        "@theia/git": "^0.3.7",
        "@theia/file-search": "^0.3.7",
        "@theia/markers": "^0.3.7",
    "@theia/java": "^0.3.7",
    "@theia/metrics":"^0.3.7",
    "switch-ws-extension": "file:/home/theia/switch-ws-extension"
    },
    "devDependencies": {
        "@theia/cli": "^0.3.7"
    }
}

I made some progress :-) I guess the extension was never correctly build so theia failed to start. I fixed the build script and I can switch the workspace via a rest call. Now I want to check if the folder exists, here is the code:

import { injectable, inject } from 'inversify';
import * as express from 'express';
import { ILogger } from "@theia/core/lib/common";
import { BackendApplicationContribution } from '@theia/core/lib/node';
import { WorkspaceServer } from '@theia/workspace/lib/common/';
import { FileSystem } from '@theia/filesystem/lib/common';
import URI from "@theia/core/lib/common/uri";

@injectable()
export class SwitchWSBackendContribution implements BackendApplicationContribution {
    constructor(
        @inject(FileSystem) protected readonly fileSystem: FileSystem,
        @inject(WorkspaceServer) protected readonly workspaceServer: WorkspaceServer,
        @inject(ILogger) protected readonly logger: ILogger) {
    }

    configure(app: express.Application) {
        app.get('/switch', (req, res) => {
            const uri = new URI(req.query.root);
            const exists = this.fileSystem.exists(uri.toString());
            if (exists) {
                const fileStat = this.fileSystem.getFileStat(uri.toString());
                if (fileStat.isDirectory) {
                    this.workspaceServer.setRoot(uri.toString());
                    res.send("Root switched to " + uri.toString());
                }
                res.send("Failed to switch root, specified root is not a folder: " + uri.toString());
            }
            res.send("Failed to switch root, specified root doesn't exist: " + uri.toString());
        });
    }
}

but compilation failed:

[compile] src/node/switchws-backend-contribution.ts(23,30): error TS2339: Property 'isDirectory' does not exist on type 'Promise<FileStat>'.

Any suggestions?

Also, I think filesystem.exist and filesystem.getFileStat return Promise, I guess the way I am calling both functions are wrong... so how to correct chain these two promises together?

thanks!

@travis1111 there are async functions, you can use async/await syntax to call them: https://medium.com/@bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8

@JanKoehnlein thanks! I got it partially working. However the switch does not work if the editor is loaded before. Let's say the editor is at http://localhost:1234, if I call http://localhost:1234/switch?root=folder before I call http://localhost:1234, then I can see the new workspace root. If I call http://localhost:1234 first, then call http://localhost:1234/switch?root=folder, then if I refresh the editor it still shows old workspace. In order to make it work, I have to close the workspace from the menu bar, then set it again, then it started to show the new workspace root. Any suggestions?

configure(app: express.Application) {
        app.get('/switch', async (req, res) => {
            const uri = new URI(req.query.root);
            const exists = await this.fileSystem.exists(uri.toString());
            if (exists) {
                const fileStat = await this.fileSystem.getFileStat(uri.toString());
                if (fileStat.isDirectory) {
                    await this.workspaceServer.setRoot(uri.toString());
                    res.send("Root switched to " + uri.toString());
                }
                res.send("Failed to switch root, specified root is not a folder: " + uri.toString());
            }
            res.send("Failed to switch root, specified root doesn't exist: " + uri.toString());
        });
    }

@travis1111 I'm not sure I understand the problem above. When you refresh with an opened editor it goes back to an old workspace? Maybe it's an issue with the layout restorer?

@epatpol yes, that is correct, it only works if I set the path first. If I opened the editor before then set the path, it doesn't work.

Can you debug workspaceServer.setRoot? I assume in this case yours is called first and then something else (triggered by opening an editor) triggers it after thus loading the first workspace?

Thanks, how to debug? I am running it in a docker container... maybe this makes this more difficulty ...

@travis1111 I believe it would be simpler for you to launch it from a debug-capable ide locally (outside) of docker to test it before running it inside docker.

If you want give us a ping on gitter and it'll be easier for us to help you setup the debug environment.

@epatpol Thanks. Before I go ahead try to setup the workspace, is there any other place I can look into? in default-workspace-server.ts, I saw this method:

protected getUserStoragePath(): string {
        return path.resolve(os.homedir(), '.theia', 'recentworkspace.json');
    }

But I don't see a folder '.theia' in home dire ('/home').

also which piece of code gets the root dir and displays it?

E.g when the browser send a GET to http://localhost:theiaport/ what happens next?

Thanks

Also wondering if it is the case that theia did not detect the change of workspace root, so decided to serve the editor from cache?

I am asking this is because, the following does not work:

  1. use rest api to change workspace root to a
  2. open editor in browser http://localhost:1234, workspace root is a
  3. call rest api again to set workspace root to b
  4. refresh editor page, workspace root is still a -> this is the problem.

However if I add a step between 3 and 4:

3a. open a new browser window and go to url http://localhost:1234 -> workspace root is now b

  1. refresh previous theia window, workspace root is also b -> now it works

So what you're saying is that you don't have a recentworkspace.json file in your home/.theia ?

@epatpol Yes, I don't even have .theia folder at all. Is this related to the problem I am having?

I'm not quite sure, you're running it inside docker right? So unless you mount your home inside the running container you should check inside it (with the user running theia) instead (maybe that's what you did though). I thought this folder was generated when a workspace was opened so maybe there's a problem with that in your environment at the moment. I can't really tell but it would be worth investigating.

There is a .theia folder inside the home directory in the docker container.

@jopit and @epatpol in deed the home is /root, not /home, so I do see that file, and it was updated correctly as well.

I switched the root to aaa (it was bbb) and before switch it was:

{"recentRoots":["file:///home/workspace/bbb"]} 

and after switch it is:

{"recentRoots":["file:///home/workspace/aaa"]}

So what else to check now :-)

it is working now, see https://github.com/theia-ide/theia/issues/1639

thanks!

Don't hesitate if you find other bugs/issues :)

@epatpol I won't... thank you!!! :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

vince-fugnitto picture vince-fugnitto  ·  3Comments

dhananjayharel picture dhananjayharel  ·  3Comments

kpge picture kpge  ·  3Comments

marechal-p picture marechal-p  ·  3Comments

tetchel picture tetchel  ·  3Comments