Skip to content

Commit

Permalink
Merge pull request #18 from chrispahm/exclude-from-multi-file-entry-p…
Browse files Browse the repository at this point in the history
…oint

Exclude from multi file entry point
  • Loading branch information
chrispahm authored Oct 11, 2023
2 parents bd8800b + 0c63a1e commit d88e423
Show file tree
Hide file tree
Showing 7 changed files with 174 additions and 138 deletions.
2 changes: 1 addition & 1 deletion dist/gams-ide.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/gams-ide.js.map

Large diffs are not rendered by default.

21 changes: 13 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "gams-ide",
"displayName": "gams-ide",
"description": "A GAMS integrated development environment for vscode",
"version": "0.0.6",
"version": "0.0.61",
"repository": {
"type": "git",
"url": "https://github.com/chrispahm/gams-ide"
Expand Down Expand Up @@ -54,12 +54,12 @@
"default": ""
},
"gamsIde.scratchDirectory": {
"description": "The (scratch) directory where linter-GAMS will read/write temp files. Ideally located on a fast internal disk.",
"description": "The (scratch) directory where gams-ide will read/write temp files. Ideally located on a fast internal disk.",
"type": "string",
"default": ""
},
"gamsIde.maxErrorsToDisplay": {
"description": "The maximum amount of errors that will be highlighted by linter-gams. Put a 0 if no maximum should be defined. Keep in mind that often only the first error is an actual GAMS error, while the subsequent errors may result from the first error.",
"description": "Maximum amount of errors that will be highlighted by gams-ide. Put a 0 if no maximum should be defined. Keep in mind that often only the first error is an actual GAMS error, while the subsequent errors may result from the first error.",
"type": "integer",
"default": 1
},
Expand All @@ -69,12 +69,12 @@
"default": true
},
"gamsIde.jumpToFirstError": {
"description": "Jump to the first error in the listing file when compilation errors are encountered.",
"description": "Automatically scroll to the first error in the listing file when compilation errors are encountered.",
"type": "boolean",
"default": true
},
"gamsIde.jumpToAbort": {
"description": "In the listing file, automatically jump to the abort parameter if present.",
"description": "If found, automatically scroll to the first abort parameter found in the listing file.",
"type": "boolean",
"default": true
},
Expand All @@ -84,7 +84,7 @@
"default": 10
},
"gamsIde.onlyAutoUnfoldDisplayStatements": {
"description": "If true, only displays will be unfolded, else all entries that fall below the treshold above will be unfolded.",
"description": "Limit 'Auto unfold listing entries treshold' to display statements. Other listing entries will not be unfolded automatically.",
"type": "boolean",
"default": true
},
Expand All @@ -94,15 +94,20 @@
"default": "p_sumRes"
},
"gamsIde.autoScrollToEndOfListing": {
"description": "If true, the listing will be scrolled to the end after a solve.",
"description": "Automatically scroll to the end of the listing after a solve.",
"type": "boolean",
"default": true
},
"gamsIde.multi_fileEntryPoint": {
"description": "You may specify the GAMS entry file for multi file models. Remember that for GGIG models these will be set by default.",
"description": "Main GAMS file to execute if your model consists of multiple files. This file will be executed when you press the 'Run' button, and compiled when saving any file in your workspace. Common multi-file entry points are 'exp_starter.gms' (FarmDyn), 'capmod.gms' (CAPRI), and 'com_.gms' (CGEBOX).",
"type": "string",
"default": "exp_starter.gms"
},
"gamsIde.excludeFromMultiFileEntryPoint": {
"description": "Exclude the following files from the multi-file entry point. This is useful if you have a file or folders that are only used for data generation, but not for the actual model. Note: Only relative and absolute paths without glob characters are supported. Relative paths are relative to the (first) workspace root.",
"type": "array",
"default": []
},
"gamsIde.commandLineArguments_compilation": {
"description": "Additional command line arguments to pass to GAMS during compilation.",
"type": "array",
Expand Down
176 changes: 89 additions & 87 deletions src/createRefTreeWithSymbolValues.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
const vscode = require('vscode');
const readline = require('readline');
const fs = require('fs');
const _ = require('lodash');
const shell = require('shelljs');
const path = require('path');
const vscode = require('vscode')
const readline = require('readline')
const fs = require('fs')
const _ = require('lodash')
const shell = require('shelljs')
const path = require('path')

module.exports = async function createRefTreeWithSymbolValues(options) {
const {
Expand Down Expand Up @@ -32,199 +32,201 @@ module.exports = async function createRefTreeWithSymbolValues(options) {
try {
await getData(lst, solves, solvesStore, referenceTree);
} catch (error) {
throw error;
throw error
}

// save new data in store
state.update("solves", solvesStore);
state.update("referenceTree", referenceTree);
};
}

function parseDMP(file, config, referenceTree) {
return new Promise((resolve, reject) => {
const stream = fs.createReadStream(file);
const stream = fs.createReadStream(file)
const rl = readline.createInterface({
input: stream,
crlfDelay: Infinity
});
})

let lineno = 0;
const defaultSettings = vscode.workspace.getConfiguration("gamsIde");
const consoleDispWidth = defaultSettings.get('consoleDispWidth');
const dumpFile = fs.createWriteStream(`${config.scratchdir}${path.sep}${path.basename(file, '.dmp')}.gms`, { flags: 'w' });
const symbols = _.filter(referenceTree, o => { return o.type === 'SET' || o.type === 'PARAM' && o.name; });
const solves = [];

rl.on('line', (line) => {
if (/solve (.*?) using/i.test(line)) {
const model = line.split(/solve/i)[1].split(/\s+/)[1];
dumpFile.write('option dispWidth=15;\ndisplay\n');
dumpFile.write('option dispWidth='+ consoleDispWidth +';\ndisplay\n');
lineno += 2;
const display = lineno + 1;
symbols.forEach((symbol) => {
dumpFile.write(`$if defined ${symbol.name} ${symbol.name} \n`);
lineno++;
});
dumpFile.write(`$if defined ${symbol.name} ${symbol.name} \n`)
lineno++
})

dumpFile.write(';\n');
dumpFile.write(';\n')
dumpFile.write(`${model}.limrow=${defaultSettings.get('consoleLimrow')};
${model}.limcol=${defaultSettings.get('consoleLimcol')};
${model}.solprint=1;
${model}.resLim=0;
option limrow=${defaultSettings.get('consoleLimrow')};
option limcol=${defaultSettings.get('consoleLimcol')};
`);
dumpFile.write(line + '\n');
lineno += 8;
`)
dumpFile.write(line + '\n')
lineno += 8

solves.push({
model: model,
line: lineno,
display: display
});
})

} else if (!/display.*?;/gi.test(line)) {
lineno++;
dumpFile.write(line + '\n');
lineno++
dumpFile.write(line + '\n')
}
});
})

rl.on('close', () => {
dumpFile.write('$show');
dumpFile.end();
fs.unlink(file, (err) => {
if (err) throw err;
});
resolve({
dumpFile,
solves
});
});
})
})

rl.on('error', reject);
});
rl.on('error', reject)
})
}

function execDMP(dumpFile, config) {
return new Promise((resolve) => {
const gamsParams = config.gamsexe + ' "' + dumpFile.path + '" suppress=1 pageWidth=80 pageSize=0 lo=3 resLim=0 -scrdir="' + config.scratchdir + '" ';
shell.cd(config.scratchdir);
return new Promise((resolve, reject) => {
const gamsParams = config.gamsexe + ' "' + dumpFile.path + '" suppress=1 pageWidth=80 pageSize=0 lo=3 resLim=0 -scrdir="' + config.scratchdir + '" '
shell.cd(config.scratchdir)

shell.exec(gamsParams, {silent: true}, (code, stdout, stderr) => {
if (code !== 0) {
console.warn('Error in dmp exec: ' + stdout, stderr);
console.log('Error in dmp exec: ' + stdout, stderr)
// reject(stderr)
}
fs.unlink(dumpFile.path, (err) => {
if (err) throw err;
});
resolve(`${config.scratchdir}${path.sep}${path.basename(dumpFile.path, '.gms')}.lst`);
});
if (err) throw err
})
resolve(`${config.scratchdir}${path.sep}${path.basename(dumpFile.path, '.gms')}.lst`)
})

});
})
}

function getData(lst, solves, gamsSolves, referenceTree) {
return new Promise((resolve, reject) => {
const stream = fs.createReadStream(lst);
const stream = fs.createReadStream(lst)
const rl = readline.createInterface({
input: stream,
crlfDelay: Infinity
});
let curSym, curData, curSection, curSolve, foundError;
})
let curSym, curData, curSection, curSolve, foundError

function save(solve, symbol, data) {
// save solve
const curSolve = _.find(solves, { 'line': Number(solve) });
const curSolve = _.find(solves, { 'line': Number(solve) })
if (curSolve) {
const statement = {
model: curSolve.model,
line: Number(solve)
};
}
if (!_.find(gamsSolves, { 'line': Number(solve) })) {
gamsSolves.push(statement);
gamsSolves.push(statement)
}
}
// save entry, overwrite any previous entries
const entry = referenceTree.find(el => {
if (el.name && symbol) return el.name.toLowerCase() === symbol.toLowerCase();
});
if (el.name && symbol) return el.name.toLowerCase() === symbol.toLowerCase()
})

if (entry) {
if (!entry.data) entry.data = {};
entry.data[`line_${Number(solve)}`] = data;
curSym = '';
curData = '';
if (!entry.data) entry.data = {}
entry.data[`line_${Number(solve)}`] = data
curSym = ''
curData = ''
}
}

rl.on('line', (line) => {
// Save current section of the listing file and the associated solve
if (line.includes('E x e c u t i o n')) {
curSection = 'Displays';
curSection = 'Displays'
} else if (line.includes('Equation Listing')) {
curSection = 'Equations';
curSolve = line.split(/[\s]+/)[8];
curSection = 'Equations'
curSolve = line.split(/[\s]+/)[8]
} else if (line.includes('Column Listing')) {
curSection = 'Variables';
curSolve = line.split(/[\s]+/)[8];
curSection = 'Variables'
curSolve = line.split(/[\s]+/)[8]
}
// save data according to sections
// Displays, Equations, Variables
else if (/^(----)\s*/.test(line)) {
if (curSym) save(curSolve, curSym, curData);
if (curSym) save(curSolve, curSym, curData)
if (curSection === 'Displays') {
const dispLine = Number(line.split(/[\s]+/)[1]);
const symbol = line.split(/[\s]+/)[3];
const pieces = line.split(/[\s]+/);
pieces.splice(0, 2);
const data = pieces.join(' ');
const solve = _.find(solves, { 'display': dispLine });
if (!solve) return;
curSym = symbol;
curSolve = solve.line;
curData = `---- ${data}`;
const dispLine = Number(line.split(/[\s]+/)[1])
const symbol = line.split(/[\s]+/)[3]
const pieces = line.split(/[\s]+/)
pieces.splice(0, 2)
const data = pieces.join(' ')
const solve = _.find(solves, { 'display': dispLine })
if (!solve) return
curSym = symbol
curSolve = solve.line
curData = `---- ${data}`
} else {
const symbol = line.split(/[\s]+/)[1];
curSym = symbol;
curData = `${line}\n`;
const symbol = line.split(/[\s]+/)[1]
curSym = symbol
curData = `${line}\n`
}
}
// sometimes set and parameters are displayed right below each other,
// therefore the above if statement won't catch these statements
else if (line.includes('PARAMETER') || line.includes('SET')) {
if (curSym) save(curSolve, curSym, curData);
if (curSym) save(curSolve, curSym, curData)
if (curSection === 'Displays') {
const symbol = line.split(/[\s]+/)[2];
const pieces = line.split(/[\s]+/);
pieces.splice(0, 1);
const data = pieces.join(' ');
curSym = symbol;
curData = `---- ${data}`;
const symbol = line.split(/[\s]+/)[2]
const pieces = line.split(/[\s]+/)
pieces.splice(0, 1)
const data = pieces.join(' ')
curSym = symbol
curData = `---- ${data}`
}
}
// abort if compilation errors
else if (line.includes('Error Messages') || line.includes('**** USER ERROR(S) ENCOUNTERED')) {
// rl.close()
// stream.destroy()
console.warn('User errors in DMP lst file', lst);
foundError = true;
reject("User error in DMP .lst file");
console.log('User errors in DMP lst file', lst);
foundError = true
reject("User error in DMP .lst file")
}
// anything else
else if (/^(\*\*\*\*)\s*\d/.test(line) || /^(GAMS)/.test(line) || line.includes("G e n e r a l") || /^(Range Statistics)/.test(line) || /^(RANGE STATISTICS)/.test(line) ) {
save(curSolve, curSym, curData);
save(curSolve, curSym, curData)
} else {
curData += line + '\n';
curData += line + '\n'
}
});
})

rl.on('close', () => {
if (foundError) return;
if (foundError) return
console.log('close and unlink', lst);
fs.unlink(lst, (err) => {
if (err) throw err;
});
resolve();
});
if (err) throw err
})
resolve()
})

rl.on('error', reject);
});
rl.on('error', reject)
})
}
Loading

0 comments on commit d88e423

Please sign in to comment.