Skip to content

Instantly share code, notes, and snippets.

@dkundel
Created August 21, 2020 00:38
Show Gist options
  • Save dkundel/3ae276f214eeb3134263e8360721e07a to your computer and use it in GitHub Desktop.
Save dkundel/3ae276f214eeb3134263e8360721e07a to your computer and use it in GitHub Desktop.
Calculator Remote Participants

Calculator

Unfinished calculator using ink.

Setup

  1. Download files
  2. npm install
  3. node index.js
const React = require('react');
const { useState, useEffect, useReducer } = require('react');
const { render, Box, Text, useInput, useApp, useFocus } = require('ink');
const useStdoutDimensions = require('ink-use-stdout-dimensions');
const Key = ({ children, onSelect }) => {
const { isFocused } = useFocus();
useInput((input, key) => {
if (key.return && isFocused) {
onSelect();
}
});
return (
<Box
borderColor={isFocused ? 'greenBright' : null}
width={5}
height={3}
borderStyle="single"
alignItems="center"
justifyContent="center"
>
<Text>{children}</Text>
</Box>
);
};
const CALCULATOR_TYPES = {
INPUT: 'input',
ADD: 'add',
SUB: 'sub',
DIV: 'div',
MULT: 'mult',
RESULT: 'result',
CLEAR: 'clear',
};
const initialState = {
currentInput: '',
currentResult: 0,
currentOperation: CALCULATOR_TYPES.CLEAR,
gatheringInput: true,
};
function reducerFunction(state, action) {
if (action.type === CALCULATOR_TYPES.CLEAR) {
return initialState;
}
if (action.type === CALCULATOR_TYPES.INPUT && state.gatheringInput) {
return { ...state, currentInput: state.currentInput + action.value };
}
if (action.type === CALCULATOR_TYPES.ADD) {
const currentInputAsNumber = parseFloat(state.currentInput);
return {
...state,
currentInput: '',
currentResult: state.currentResult + currentInputAsNumber,
currentOperation: action.type,
};
}
if (action.type === CALCULATOR_TYPES.RESULT) {
const currentInputAsNumber = parseFloat(state.currentInput);
const currentResult = state.currentResult + currentInputAsNumber;
return {
...state,
currentInput: currentResult.toString(),
currentResult: currentResult,
currentOperation: action.type,
gatheringInput: false,
};
}
return state;
}
function toSymbol(op) {
switch (op) {
case CALCULATOR_TYPES.ADD:
return '+';
case CALCULATOR_TYPES.SUB:
return '-';
case CALCULATOR_TYPES.DIV:
return '/';
case CALCULATOR_TYPES.MULT:
return '*';
case CALCULATOR_TYPES.RESULT:
return '=';
case CALCULATOR_TYPES.CLEAR:
return ' ';
}
}
const App = () => {
const [width, height] = useStdoutDimensions();
const [state, dispatch] = useReducer(reducerFunction, initialState);
const { exit } = useApp();
const add = () => {
dispatch({ type: CALCULATOR_TYPES.ADD });
};
const sub = () => {
dispatch({ type: CALCULATOR_TYPES.SUB });
};
const div = () => {
dispatch({ type: CALCULATOR_TYPES.DIV });
};
const result = () => {
dispatch({ type: CALCULATOR_TYPES.RESULT });
};
const mult = () => {
dispatch({ type: CALCULATOR_TYPES.MULT });
};
useInput((input, key) => {
if (input === 'q') {
exit(0);
} else if (input.match(/[\d\.]/)) {
if (input === '.' && state.currentInput.includes('.')) {
return;
}
dispatch({ type: CALCULATOR_TYPES.INPUT, value: input });
} else if (key.escape) {
dispatch({ type: CALCULATOR_TYPES.CLEAR });
}
});
return (
<Box
flexDirection="column"
width={width}
alignItems="center"
justifyContent="center"
height={height}
margin={1}
padding={2}
>
<Box flexDirection="column" borderStyle="double" width={31}>
<Box height={3} paddingRight={1}>
<Box height={3} alignItems="center">
<Text>{toSymbol(state.currentOperation)}</Text>
</Box>
<Box height={3} flexGrow={1} borderStyle="single">
<Text>{state.currentInput}</Text>
</Box>
</Box>
<Box
marginTop={1}
width="100%"
flexDirection="row"
justifyContent="space-around"
>
<Key onSelect={add}>{'+'}</Key>
<Key onSelect={sub}>{'-'}</Key>
<Key onSelect={result}>{'='}</Key>
<Key onSelect={div}>{'/'}</Key>
<Key onSelect={mult}>{'*'}</Key>
</Box>
</Box>
</Box>
);
};
async function renderApp() {
const { waitUntilExit } = render(<App />);
await waitUntilExit();
console.log('Bye');
}
module.exports = { renderApp };
const importJsx = require('import-jsx');
const { renderApp } = importJsx('./App.jsx');
renderApp().catch(console.error);
{
"name": "calculator",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "Dominik Kundel <[email protected]> (https://dkundel.com)",
"license": "MIT",
"dependencies": {
"import-jsx": "^4.0.0",
"ink": "^3.0.4",
"ink-use-stdout-dimensions": "^1.0.5",
"react": "^16.13.1"
}
}
@philnash
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment