-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
@@ -192,7 +193,8 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/cn.js b/src/cn.js
index 2dc3dd9a..dd89a059 100644
--- a/src/cn.js
+++ b/src/cn.js
@@ -26,6 +26,7 @@
const cnFile = `${D.el.app.getPath('userData')}/connections.json`;
const lcnFile = `${D.el.app.getPath('userData')}/last_configuration.json`;
let protocolLogFile;
+ const lastconfig = 'last configuration';
const defaultProtocolLogFile = path.join(
D.el.app.getPath('temp'),
`RIDE-${D.versionInfo.version}-${D.el.process.pid}.log`,
@@ -91,6 +92,103 @@
},
), 10);
};
+ const formatInterpreters = (interpretersList) => {
+ interpretersList
+ .sort((x, y) => cmpVer(y.ver, x.ver) || +y.bits - +x.bits
+ || (y.edition === 'unicode') - (x.edition === 'unicode')
+ || (y.opt > x.opt) - (y.opt < x.opt))
+ .forEach((x) => {
+ x.supported = cmpVer(x.ver, MIN_V) >= 0;
+ x.name = `v${
+ x.ver.join('.')}, ${
+ x.bits}-bit, ${
+ x.edition.replace(/^./, (w) => w.toUpperCase())}${
+ x.opt ? `, ${x.opt}` : ''}${
+ x.supported ? '' : ' (unsupported)'}`;
+ });
+ };
+ const getLocalInterpreters = () => { // collect information about installed interpreters
+ interpreters.splice(0);
+ try {
+ if (/^win/.test(process.platform)) {
+ const s = cp.execSync(
+ 'reg query "HKEY_CURRENT_USER\\Software\\Dyalog" /s /v localdyalogdir',
+ { timeout: 4000, encoding: 'UTF8' },
+ );
+ let b; // b:bits
+ let v; // v:version
+ let u; // u:edition
+ let n; // n:match object
+ s && s.split('\r\n').forEach((x) => {
+ if (x) {
+ if ((n = /^HK.*\\Dyalog APL\/W(-64)? (\d+\.\d+)( Unicode)?$/i.exec(x))) {
+ [, b, v, u] = n;
+ b = b ? 64 : 32;
+ u = u ? 'unicode' : 'classic';
+ } else if (v && (n = /^ *localdyalogdir +REG_SZ +(\S.*)$/i.exec(x))) {
+ interpreters.push({
+ exe: `${n[1]}\\dyalog.exe`,
+ ver: parseVer(v),
+ bits: b,
+ edition: u,
+ opt: '',
+ });
+ } else if (!/^\s*$/.test(x)) {
+ b = null;
+ v = null;
+ u = null;
+ }
+ }
+ });
+ } else if (process.platform === 'darwin') {
+ const rd = '/Applications';
+ ls(rd).forEach((x) => {
+ const n = /^Dyalog-(\d+\.\d+)\.app$/.exec(x);
+ const exe = `${rd}/${x}/Contents/Resources/Dyalog/mapl`;
+ n && fs.existsSync(exe) && interpreters.push({
+ exe,
+ ver: parseVer(n[1]),
+ bits: 64,
+ edition: 'unicode',
+ opt: '',
+ });
+ });
+ } else {
+ const rd = '/opt/mdyalog';
+ const sil = (g) => (x) => { try { g(x); } catch (_) { /* exception silencer */ } };
+ ls(rd).forEach(sil((v) => {
+ if (/^\d+\.\d+/.test(v)) {
+ ls(`${rd}/${v}`).forEach(sil((b) => {
+ if (b === '32' || b === '64') {
+ ls(`${rd}/${v}/${b}`).forEach(sil((u) => {
+ if (u === 'unicode' || u === 'classic') {
+ const exe = `${rd}/${v}/${b}/${u}/mapl`;
+ fs.existsSync(exe) && interpreters.push({
+ exe,
+ ver: parseVer(v),
+ bits: +b,
+ edition: u,
+ opt: '',
+ });
+ }
+ }));
+ }
+ }));
+ }
+ }));
+ }
+ } catch (e) { console.error(e); }
+ formatInterpreters(interpreters);
+ };
+ const createPresets = () => {
+ D.conns.push(...interpreters.filter((x) => x.supported).map((int) => ({
+ name: int.name,
+ type: 'start',
+ subtype: 'raw',
+ exe: int.exe,
+ preset: true,
+ })));
+ };
const save = () => {
const names = $('.name', q.favs).toArray().map((x) => x.innerText);
const dups = names.filter((a, i) => names.indexOf(a) !== i);
@@ -99,7 +197,7 @@
`The following name${dups.length ? 's are' : ' is'} duplicated:\n${dups.join('\n')}`,
'Duplicate connection names',
() => {
- $(q.favs).list('select', names.lastIndexOf(dups[0]));
+ $(q.favs).list('select', names.indexOf(dups[0]));
$(q.fav_name).focus();
},
);
@@ -109,15 +207,11 @@
const r = $.confirm('Connections file has been modified, do you want to overwrite with your changes?');
if (!r) return;
}
- const a = q.favs.children;
- const b = [];
- for (let i = 0; i < a.length; i++) {
- const conf = a[i].cnData;
- conf.name !== 'last configuration' && b.push(conf);
- }
- D.conns = b;
+ const b = [...q.favs.children]
+ .map((x) => x.cnData)
+ .filter((x) => x.name !== lastconfig && !x.preset);
try {
- fs.writeFileSync(cnFile, JSON.stringify(D.conns));
+ fs.writeFileSync(cnFile, JSON.stringify(b));
D.conns_modified = +fs.statSync(cnFile).mtime;
toastr.success(cnFile, 'Configuration saved.');
} catch (e) {
@@ -126,7 +220,7 @@
};
const saveLastConf = (conf) => {
try {
- fs.writeFileSync(lcnFile, JSON.stringify({ ...conf, name: 'last configuration' }));
+ fs.writeFileSync(lcnFile, JSON.stringify({ ...conf, name: lastconfig }));
} catch (e) {
toastr.error(`${e.name}: ${e.message}`, 'Save failed');
}
@@ -140,17 +234,9 @@
};
const updExes = () => {
const ssh = q.subtype.value === 'ssh';
- const h = (ssh ? interpretersSSH : interpreters)
- .sort((x, y) => cmpVer(y.ver, x.ver) || +y.bits - +x.bits
- || (y.edition === 'unicode') - (x.edition === 'unicode')
- || (y.opt > x.opt) - (y.opt < x.opt))
- .map((x) => {
- let s = `v${x.ver.join('.')}, ${x.bits}-bit, ${x.edition.replace(/^./, (w) => w.toUpperCase())}${x.opt ? `, ${x.opt}` : ''}`;
- const supported = cmpVer(x.ver, MIN_V) >= 0;
- supported || (s += ' (unsupported)');
- return `