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

Color Schemes In Terminal #484

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
202 changes: 199 additions & 3 deletions apps/shell/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const url = require('url');
const yaml = require('js-yaml');
const glob = require("glob");
const uuidv4 = require('uuid/v4');
const os = require('os');
const termSchemes = require('term-schemes');
const port = 3000;
const host_path_rx = `/session/([a-f0-9\-]+)/([^\\/\\?]+)([^\\?]+)?(\\?.*)?$`;

Expand All @@ -26,6 +28,137 @@ if (fs.existsSync('.env')) {
dotenv.config({path: '.env'});
}

//Start Terminal Color Scheme Implementation
//declared constants for directory paths
const xdg_config_dir = (process.env["XDG_CONFIG_HOME"] || path.join(os.homedir(), ".config"));
const ood_app_config_root = (process.env["OOD_APP_CONFIG_ROOT"] || '/etc/ood/config/ondemand/apps/shell');
const userDir = path.join(xdg_config_dir, "ondemand", "apps", "shell", "themes");
const systemDir = path.join(ood_app_config_root, "themes");

//Search directories and make directory if not present.
fs.mkdirSync(userDir, {recursive: true});
var schemeObjects = {...getSchemeObjects(userDir), ...getSchemeObjects(systemDir)};

/**
* Parse through file information in certain directories.
* @param {String} dir - The target directory.
* @return {Object} - The key information returned is an object within an object.
*/
function getSchemeObjects(dir) {
samirmansour marked this conversation as resolved.
Show resolved Hide resolved
var schemes = {};

try {
fs.readdirSync(dir).forEach(function(file) {
fileInfo = path.parse(file);
schemes[fileInfo.name] = {name: fileInfo.name, file: fileInfo.base, ext: fileInfo.ext, dir: dir}
});
return schemes;
} catch (err) {
return {};
}
}

/**
* Maps schemeObject to an array for frontend.
* @return {Array} - An array of shemeObjects.
*/
function getSchemeFilesArray() {

return Object.keys(schemeObjects).map(i => schemeObjects[i])
}

/**
* Takes a number and converts it to a hex number.
* @param {Int} num - The number to convert.
* @return {String} - The hex number.
*/
function rgbToHexMath (num) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add some documentation above all of these functions following https://jsdoc.app/ format

var hex = Number(num).toString(16);
if (hex.length < 2) {
hex = "0" + hex;
}
return hex;
};

/**
* Converts a complete array of colors to a hex color value.
* @param {Array} array - The colors to convert.
* @return {String} - The hex code for the color.
*/
function hexConverter (array) {
var red = array[0];
var green = array[1];
var blue = array[2];

return `#${rgbToHexMath(red)}${rgbToHexMath(green)}${rgbToHexMath(blue)}`.toUpperCase();
}

/**
* Show the host of the specific terminal.
* @param {String} uuid - The id of the terminal.
* @return {String} - The host of the specific terminal.
*/
function findHost(uuid) {
sessions = terminals.instances;
var host = sessions[uuid].host;

return host;
}

/**
* Convert file with scheme to an object of colors.
* @param {Object} fileObject - An object with information on file location and ext.
* @return {Object} - The colors parsed into an object.
*/
function parseFile(fileObject) {

const ext = fileObject.ext;
const file = fileObject.dir + "/" + fileObject.file;
const raw = String(fs.readFileSync(file));

const schemes = {
".itermcolors": termSchemes.iterm2,
".colorscheme": termSchemes.konsole,
".colors": termSchemes.remmina,
".terminal":termSchemes.terminal,
".config": termSchemes.terminator,
".config_0": termSchemes.tilda,
".theme": termSchemes.xfce,
".txt": termSchemes.termite,
".Xresources": termSchemes.xresources,
".xrdb": termSchemes.xresources,
}
try {
return schemes[ext](raw)
} catch (err) {
return {error: "unknown file type."}
}
}

/**
* Convert rgb color format to hex color codes.
* @param {Object} obj - The object of rgb colors.
* @return {Object} - The object of hex colors.
*/
function convertSchemeObject(obj) {
newSchemeObj = {};
colorArray = [];
for (var key of Object.keys(obj)) {
if(isNaN(key) === false) {

colorArray.push(hexConverter(obj[key]));

} else if (isNaN(key)) {
newSchemeObj[key] = hexConverter(obj[key]);
}

}

newSchemeObj["colorPaletteOverrides"] = colorArray;

return newSchemeObj;
}

const tokens = new Tokens({});
const secret = tokens.secretSync();

Expand All @@ -43,20 +176,83 @@ router.get('/ssh*', function (req, res) {

});


//For laumch page to start a new session with color scheme and host.
router.get('/new-session', function(req, res, next) {
var id = uuidv4();


res.redirect(url.format({
pathname: req.baseUrl + "/custom-term",
query: {
"host": req.query.host + ".osc.edu",
"scheme": req.query.scheme,
"session": id
}
}));

});

router.get('/custom-term', function(req, res, next) {
res.locals.uuid = req.query.session;
var fileObject, schemeObject, schemeColorConvert;
var defaultObj = {
'use-default-window-copy': true,
'ctrl-v-paste': true,
'ctrl-c-copy': true,
'cursor-blink': true,
};

res.locals.schemeObject;
if (req.query.scheme === "default") {
if ('default' in schemeObjects) {
fileObject = schemeObjects[req.query.scheme];
schemeObject = parseFile(fileObject);
schemeColorConvert = convertSchemeObject(schemeObject);
res.locals.schemeObject = schemeColorConvert;
} else {

res.locals.schemeObject = defaultObj;
}
} else {

fileObject = schemeObjects[req.query.scheme];
schemeObject = parseFile(fileObject);
schemeColorConvert = convertSchemeObject(schemeObject);
res.locals.schemeObject = schemeColorConvert;
}

next();

}, function(req, res, next) {
res.locals.host = req.query.host || findHost(req.query.session);
console.log(res.locals.schemeObject);
var cookieValue = JSON.stringify(res.locals.schemeObject);

res.cookie(res.locals.uuid, cookieValue, {expires: new Date(Date.now() + 8 * 3600000) });

next();

}, function(req, res, next) {

res.redirect(req.baseUrl + `/session/${req.query.session}/${res.locals.host}`)
})


router.get('/session/:id*', function (req, res) {

res.render('index',
{
baseURI: req.baseUrl,
csrfToken: tokens.create(secret),
session: req.params.id
});

});

router.get('/launch', function (req, res) {

res.render('launch', {baseURI: req.baseUrl, sessions: terminals.sessionsInfo()});

res.render('launch', {baseURI: req.baseUrl, sessions: terminals.sessionsInfo(), fileOptions: getSchemeFilesArray() || []});
})

router.use(express.static(path.join(__dirname, 'public')));
Expand Down Expand Up @@ -88,7 +284,7 @@ var terminals = {
var args = dir ? [host, '-t', 'cd \'' + dir.replace(/\'/g, "'\\''") + '\' ; exec ${SHELL} -l'] : [host];

process.env.LANG = 'en_US.UTF-8'; // this patch (from b996d36) lost when removing wetty (2c8a022)

this.instances[uuid] = {term: pty.spawn(cmd, args, {
name: 'xterm-256color',
cols: 80,
Expand Down
3 changes: 2 additions & 1 deletion apps/shell/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"minimist": ">=1.2.2",
"node-pty": "^0.9.0",
"ws": ">=7.2.0",
"uuid": "^3.3.3"
"uuid": "^3.3.3",
"term-schemes": "1.2.1"
},
"private": true,
"resolutions": {
Expand Down
43 changes: 43 additions & 0 deletions apps/shell/public/javascripts/ood_shell.1.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,46 @@
function getCookie(uuid) {

var cookie = document.cookie.match('(^|[^;]+)\\s*' + uuid + '\\s*=\\s*([^;]+)')

return cookie ? cookie.pop() : '';

}

function CustomTerm(uuid) {
this.uuid = uuid;
}

CustomTerm.prototype.getTermPrefs = function () {

var defaultPref = {
'use-default-window-copy': true,
'ctrl-v-paste': true,
'ctrl-c-copy': true,
'cursor-blink': true,
};

if (getCookie(this.uuid)) {
var decodedTheme = decodeURIComponent(getCookie(this.uuid));
var jsonTheme = JSON.parse(decodedTheme);

pref = {
'use-default-window-copy': true,
'ctrl-v-paste': true,
'ctrl-c-copy': true,
'cursor-blink': true,
'background-color': jsonTheme['background'],
'foreground-color': jsonTheme['text'],
'color-palette-overrides': jsonTheme['colorPaletteOverrides'],
'cursor-color': jsonTheme['cursor'] + '50',
};

return pref;
}

return defaultPref;
}



// Object that defines a terminal element
function OodShell(element, url, prefs) {
Expand Down
58 changes: 48 additions & 10 deletions apps/shell/public/stylesheets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,57 @@ html, body {
}
/* For Launch page*/

table {
border-collapse: collapse;
width: 100%;
.split {
height: 100%;
width: 50%;
position: fixed;
z-index: 1;
top: 0;
overflow-x: hidden;
padding-top: 20px;
}

th, td {
text-align: left;
padding: 8px;
.left {
left: 0;
background-color: #F0E9E9;
}

tr:nth-child(even){background-color: #f2f2f2}
.right {
right: 0;
background-color: #F0E9E9;
}

th {
background-color: #FF0000;
color: white;
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
}

.bubble {
padding: 10px;
background-color: white;
height: 500px;
width: 400px;
border-radius: 20px;
-moz-box-shadow: 2px 2px 5px #333;
-webkit-box-shadow: 2px 2px 5px #333;
box-shadow: 2px 2px 5px #333;
}

.drop {
margin-top: 10px;
width: 200px;
height: 30px;
border-radius: 50px;
}

.custom-label {
font-size: 20px;
}

.button {
height: 40px;
border-radius: 5px;
}
6 changes: 5 additions & 1 deletion apps/shell/views/index.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@
// hterm default preferences are defined here. Switch to the tag that we're using.
// https://chromium.googlesource.com/apps/libapps/+/master/hterm/js/hterm_preference_manager.js

oodShell = new OodShell(terminalContainer, webSocketUrl, terminalPrefs);
var uuid = "{{session}}";
var customTerm = new CustomTerm(uuid);

oodShell = new OodShell(terminalContainer, webSocketUrl, customTerm.getTermPrefs());

oodShell.createTerminal();
}

Expand Down
Loading