Skip to content

Commit aef35ad

Browse files
committed
🚀 Launch Juno in specified directory
1 parent 1a40e86 commit aef35ad

File tree

3 files changed

+53
-35
lines changed

3 files changed

+53
-35
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,7 @@ Feel free to [report issues](https://github.com/uetchy/juno/issues/new) you find
4747

4848
## Upcoming
4949

50-
- [ ] Restart command
51-
- [ ] Launch Juno in specified directory
50+
- [x] Launch Juno in specified directory
5251
- [ ] Terminal integration
5352
- [ ] Test suite
5453
- [ ] Auto update

index.js

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,31 +9,10 @@ const {app, dialog, shell, Menu, Tray} = require('electron'); // eslint-disable-
99
// Our modules
1010
const jupyter = require('./jupyter');
1111

12-
// Load config
13-
const userConfigPath = resolve(homedir(), '.junorc.json');
14-
const defaultConfig = {
15-
jupyterCommand: resolve(homedir(), '.pyenv', 'shims', 'jupyter-notebook'),
16-
jupyterPort: 8888,
17-
openBrowserOnStartup: true
18-
};
19-
let globalConfig;
20-
try {
21-
const userConfig = require(userConfigPath);
22-
globalConfig = extend(defaultConfig, userConfig);
23-
} catch (err) {
24-
fs.writeFileSync(userConfigPath, JSON.stringify(defaultConfig, null, ' '), 'utf-8');
25-
globalConfig = defaultConfig;
26-
}
27-
28-
// Global instances
29-
let tray = null;
30-
let jupyterPID = null;
31-
let notebooksToOpen = [];
32-
3312
// Supress multiple instances
3413
const shouldQuit = app.makeSingleInstance(argv => {
3514
const notebooks = argv.slice(2);
36-
jupyter.openBrowser(notebooks, globalConfig.jupyterPort);
15+
openBrowser(notebooks);
3716
});
3817

3918
// Quit if the app instance is secondary one
@@ -42,9 +21,41 @@ if (shouldQuit) {
4221
return;
4322
}
4423

24+
// Global instances
25+
let tray = null;
26+
let jupyterPID = null;
27+
let notebooksToOpen = [];
28+
let globalConfig = null;
29+
30+
// Global constants
31+
const userConfigPath = resolve(homedir(), '.junorc.json');
32+
const nbConfigPath = resolve(homedir(), '.jupyter/nbconfig', 'notebook.json');
33+
const defaultConfig = {
34+
jupyterCommand: resolve(homedir(), '.pyenv', 'shims', 'jupyter-notebook'),
35+
jupyterPort: 8888,
36+
jupyterHome: homedir(),
37+
openBrowserOnStartup: true
38+
};
39+
40+
// Load config and merge to default config
41+
function loadConfig() {
42+
let config;
43+
try {
44+
const userConfig = require(userConfigPath);
45+
config = extend(defaultConfig, userConfig);
46+
} catch (err) {
47+
fs.writeFileSync(userConfigPath, JSON.stringify(defaultConfig, null, ' '), 'utf-8');
48+
config = defaultConfig;
49+
}
50+
return config;
51+
}
52+
53+
// Load config
54+
globalConfig = loadConfig();
55+
4556
// Open browser and show notebooks
4657
function openBrowser(notebooks) {
47-
jupyter.openBrowser(notebooks, globalConfig.jupyterPort);
58+
jupyter.openBrowser(notebooks, globalConfig.jupyterHome, globalConfig.jupyterPort);
4859
}
4960

5061
// Open browser when files are passed
@@ -85,8 +96,11 @@ app.on('ready', () => {
8596
{label: 'New Notebook', accelerator: 'Command+N', click: () => {
8697
dialog.showSaveDialog({
8798
title: 'New Notebook',
88-
defaultPath: resolve(homedir(), 'Untitled.ipynb')
99+
defaultPath: resolve(globalConfig.jupyterHome, 'Untitled.ipynb')
89100
}, filepath => {
101+
if (!filepath) {
102+
return;
103+
}
90104
const defaultNotebook = {
91105
cells: [],
92106
metadata: {},
@@ -122,7 +136,13 @@ app.on('ready', () => {
122136
notebooksToOpen = [];
123137

124138
// Launch or pick up jupyter daemon and get PID
125-
jupyterPID = jupyter.getJupyterProcess(globalConfig.jupyterCommand, globalConfig.jupyterPort);
139+
jupyterPID = jupyter.getJupyterProcess(
140+
globalConfig.jupyterCommand,
141+
globalConfig.jupyterHome,
142+
globalConfig.jupyterPort
143+
);
144+
145+
// Open browser to show notebooks
126146
if (notebooks.length > 0 || globalConfig.openBrowserOnStartup) {
127147
openBrowser(notebooks);
128148
}

jupyter.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
const {execSync, exec, spawn} = require('child_process');
2-
const {homedir} = require('os');
32
const {relative} = require('path');
43

54
// Return a process pid which is listening specific port
@@ -14,33 +13,33 @@ function processListening(port) {
1413
}
1514

1615
// Launch jupyter daemon and returns pid
17-
function launchJupyter(jupyterPath, targetPath, port) {
16+
function launchJupyter(command, rootPath, port) {
1817
console.log('Launching Jupyter ...');
19-
const options = [targetPath, `--port=${port}`, '--no-browser'];
20-
const jupyter = spawn(jupyterPath, options, {detached: true});
18+
const options = [rootPath, `--port=${port}`, '--no-browser'];
19+
const jupyter = spawn(command, options, {detached: true});
2120
return jupyter.pid;
2221
}
2322

2423
// Open browser and show notebooks
25-
function openBrowser(notebooks, port) {
24+
function openBrowser(notebooks, rootPath, port) {
2625
if (notebooks.length === 0) {
2726
exec(`open http://localhost:${port}/tree`);
2827
} else {
2928
notebooks.forEach(notebook => {
30-
const target = relative(homedir(), notebook);
29+
const target = relative(rootPath, notebook);
3130
exec(`open http://localhost:${port}/notebooks/${target}`);
3231
});
3332
}
3433
}
3534

3635
// Fetch or launch jupyter and returns their PID
37-
function getJupyterProcess(jupyterPath, port) {
36+
function getJupyterProcess(command, rootPath, port) {
3837
// Fetch existing process
3938
let pid = processListening(port);
4039

4140
// Launch Jupyter if not existed
4241
if (!pid) {
43-
launchJupyter(jupyterPath, homedir(), port);
42+
launchJupyter(command, rootPath, port);
4443
console.log('Started');
4544
}
4645
while (!pid) {

0 commit comments

Comments
 (0)