Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucretius committed Mar 14, 2018
0 parents commit a8f6ba6
Show file tree
Hide file tree
Showing 6 changed files with 471 additions and 0 deletions.
61 changes: 61 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Typescript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Hypermocil
### An itermocil port for Hyper terminal.

I use itermocil a lot, and really missed it in Hyper. This is my attempt at a port. It is currently very buggy. The way to invoke is by echoing the command you would normally send to itermocil, so if you would use

`itermocil my_file`

You would then use

`echo "hypermocil my_file"`. This is a hacky way of getting around the SESSION_DATA issue and can easily be fixed by creating an entry in the bash_profile which does this echo, so you can get auto-completion.

All itermocil layouts are supported. Currently only a single window definition, with up to 9 panes can be specified, and they must use the `-commands` array (no single-line commands yet)

Border colors are also hard-coded at the moment (something I will fix shortly).

Basically, this is like early early early alpha.

The accepted file structure:

`my_config.yml`

```
windows:
- name: hyperterm
root: ~/workspace/my_workspace
layout: even-vertical
panes:
- commands:
- echo "pane 1"
- echo "again here"
- commands:
- echo "pane 2"
- ls -l
- commands:
- echo "pane 3"
- commands:
- echo "pane 4"
- commands:
- echo "pane 5"
- commands:
- echo "pane 6"
```

126 changes: 126 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
const YAML = require('yamljs');
const path = require('path');
const _ = require('lodash');
const uuid = require('uuid');

const resolveHome = (filepath) => {
if (filepath[0] === '~') {
return path.join(process.env.HOME, filepath.slice(1));
}
return filepath;
}

const getFileName = (data) => {
return _.last(new RegExp('\nhypermocil (.*?)\r.*').exec(data));
}

let savedChars = '';

exports.middleware = (store) => (next) => (action) => {
if ('SESSION_ADD_DATA' === action.type) {
const { data } = action;

if (detectHypermocilCommand(data)) {
const filename = getFileName(data);
const yamlConfig = YAML.load(resolveHome(`~/.itermocil/${filename}.yml`));
_.each(yamlConfig.windows, w => {
window.rpc.emit('new', { isNewGroup: true, cols: 20, rows: 20, cwd: resolveHome(w.root) })
for (let i = 1; i < w.panes.length; i++) {
window.rpc.emit('new', { splitDirection: 'HORIZONTAL', cwd: resolveHome(w.root) })
}
});

store.dispatch({
type: 'CREATE_HYPERMOCIL_WINDOWS',
hypermocilLayout: yamlConfig.windows[0].layout,
hypermocilPaneCount: yamlConfig.windows[0].panes.length,
hypermocilPanes: yamlConfig.windows[0].panes
});
} else {
next(action);
}
} else {
next(action);
}
}

exports.reduceUI = (state, action) => {
switch (action.type) {
case 'CREATE_HYPERMOCIL_WINDOWS':
state = state.set('hypermocilLayout', action.hypermocilLayout);
state = state.set('hypermocilPaneCount', action.hypermocilPaneCount);
state = state.set('hypermocilPanes', action.hypermocilPanes);
}
return state;
};

exports.decorateConfig = (config) => {
debugger;
return Object.assign({}, this.props, {
css: `
${config.css || ''}
${require('./styles.js')}
`
});
}

const termCommands = {};

exports.mapTermsState = (state, map) => {
return Object.assign(map, {
hypermocilLayout: state.ui.hypermocilLayout,
hypermocilPaneCount: state.ui.hypermocilPaneCount,
hypermocilPanes: state.ui.hypermocilPanes
});
};

const passProps = (uid, parentProps, props) => {
return Object.assign(props, {
hypermocilLayout: parentProps.hypermocilLayout,
hypermocilPaneCount: parentProps.hypermocilPaneCount,
hypermocilPanes: parentProps.hypermocilPanes
});
}

exports.getTermGroupProps = passProps;
exports.getTermProps = passProps;
let commandsExecuted;

exports.decorateTerm = (Term, { React, notify }) => {
return class extends React.Component {
constructor(props, context) {
super(props, context);
this._onTerminal = this._onTerminal.bind(this);
}
_onTerminal(term) {
if (this.props.onTerminal) this.props.onTerminal(term);
const isActiveTermGroup = term.div_.parentElement.parentElement.parentElement.parentElement.classList.contains("terms_termGroupActive");
if (isActiveTermGroup) {
if (_.isNil(commandsExecuted) || commandsExecuted === 0) {
commandsExecuted = this.props.hypermocilPaneCount;
}
const commands = _.get(this.props, `hypermocilPanes[${this.props.hypermocilPaneCount - commandsExecuted}].commands`, []);
commandsExecuted--;
term.div_.parentElement.parentElement.parentElement.classList.add(`itermocil-${this.props.hypermocilLayout}`)
term.div_.parentElement.parentElement.parentElement.classList.add(`itermocil`)
term.div_.parentElement.parentElement.classList.add(`itermocilTab`)
const originalTermHandler = term.onTerminalReady;
term.onTerminalReady = () => {
originalTermHandler();
for (let i = 0; i < commands.length; i++) {
term.io.sendString(commands[i] + "\r");
}
};
}
}
render() {
return React.createElement(Term, Object.assign({}, this.props, {
onTerminal: this._onTerminal
}));
}
}
}

function detectHypermocilCommand(data) {
return new RegExp('\nhypermocil .*\r.*').test(data)
}
19 changes: 19 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "hypermocil",
"version": "2.0.1",
"description": "Itermocil for HyperTerm",
"author": "Robert Lippens <[email protected]>",
"license": "MIT",
"main": "index.js",
"keywords": [
"hyper",
"hyperterm",
"hypermocil",
"itermocil"
],
"dependencies": {
"lodash": "^4.17.5",
"uuid": "^3.2.1",
"yamljs": "^0.3.0"
}
}
133 changes: 133 additions & 0 deletions styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
module.exports = `
.itermocil > .splitpane_divider {
display: none !important;
}
.itermocil-3-columns {
display: flex;
flex-wrap: wrap;
flex-direction: row !important;
flex: 3;
}
.itermocil-3-columns>div {
flex-basis: 33% !important;
flex-grow: 3 !important;
border: 1px solid #333;
}
.itermocil-tiled {
display: flex;
flex-wrap: wrap;
flex: 2;
flex-direction: row !important
}
.itermocil-tiled>div {
flex-basis: 49% !important;
flex-grow: 2 !important;
border: 1px solid #333;
}
.itermocil-main-vertical {
display: inline-flex;
flex: 8;
flex-flow: column wrap;
height: 100%;
}
.itermocil-main-vertical>div {
flex: 1;
flex-basis: 1 !important;
flex-grow: 1 !important;
border: 1px solid #333;
margin:-1px;
}
.itermocil-main-vertical>div:first-child {
flex-basis: 100% !important;
flex-grow: 9 !important;
height: 100%;
}
.itermocil-main-vertical-flipped {
display: inline-flex;
flex: 9;
flex-flow: column wrap;
height: 100%;
}
.itermocil-main-vertical-flipped>div {
flex: 1;
border: 1px solid #333;
}
.itermocil-main-vertical-flipped>div:last-child {
flex-basis: 100%;
flex-grow: 9;
height: 100%;
}
.itermocil-double-main-horizontal {
display: flex;
flex-wrap: wrap;
flex: 9;
flex-direction: row !important;
}
.itermocil-double-main-horizontal>div {
flex: 1 !important;
flex-basis: 13% !important;
flex-grow: 5 !important;
border: 1px solid #333;
}
// accounting for extra div
.itermocil-double-main-horizontal>div:nth-last-child(2),
.itermocil-double-main-horizontal>div:nth-last-child(4) {
flex-basis: 49% !important;
flex-grow: 4.5 !important;
}
.itermocil-double-main-vertical {
display: inline-flex;
flex: 8;
flex-flow: column wrap;
height: 100%;
flex-direction: column !important;
}
.itermocil-double-main-vertical>div {
flex: 1 !important;
border: 1px solid #333;
}
// nth-child(3) to account for border div
.itermocil-double-main-vertical>.itermocilTab:first-child,
.itermocil-double-main-vertical>.itermocilTab:nth-child(3) {
flex-basis: 100% !important;
flex-grow: 9 !important;
height: 100%;
}
.itermocil-even-vertical {
display: flex;
flex-direction: column;
}
.itermocil-even-vertical>div {
flex: 1;
border-bottom: 1px solid #333;
}
.itermocil-even-horizontal {
display: flex !important;
flex-direction: row !important;
}
.itermocil-even-horizontal>div {
flex: 1 !important;
border-right: 1px solid #333;
}
`;
Loading

0 comments on commit a8f6ba6

Please sign in to comment.