-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from gtktsc/ascii-57-add-simple-cli
ascii-57: add simple cli
- Loading branch information
Showing
12 changed files
with
1,624 additions
and
437 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
#!/usr/bin/env node | ||
|
||
import * as yargs from 'yargs'; | ||
import plot from './index'; | ||
import { MultiLine, Settings } from './types'; | ||
|
||
const { argv } = yargs | ||
.option('input', { | ||
alias: 'i', | ||
type: 'string', | ||
demandOption: true, | ||
}) | ||
.option('options', { | ||
alias: 'o', | ||
type: 'string', | ||
description: 'plot settings', | ||
}) | ||
.option('height', { | ||
alias: 'h', | ||
type: 'number', | ||
description: 'plot height', | ||
}) | ||
.option('hideXAxis', { | ||
type: 'boolean', | ||
description: 'hide x axis', | ||
}) | ||
.option('hideYAxis', { | ||
type: 'boolean', | ||
description: 'hide Y axis', | ||
}) | ||
.option('fillArea', { | ||
type: 'boolean', | ||
description: 'fill plot area', | ||
}) | ||
.option('width', { | ||
alias: 'w', | ||
type: 'number', | ||
description: 'plot width', | ||
}) | ||
.option('title', { | ||
alias: 't', | ||
type: 'string', | ||
description: 'plot title', | ||
}) | ||
.option('xLabel', { | ||
type: 'string', | ||
description: 'x axis label', | ||
}) | ||
.option('color', { | ||
alias: 'c', | ||
type: 'array', | ||
description: 'plot colors', | ||
}) | ||
.option('axisCenter', { | ||
type: 'array', | ||
description: 'plot center coordinates', | ||
}) | ||
.option('yLabel', { | ||
type: 'string', | ||
description: 'y axis label', | ||
}); | ||
|
||
const withError = (cb: () => unknown) => { | ||
try { | ||
cb(); | ||
} catch (error) { | ||
process.stderr.write('Oops! Something went wrong!\n'); | ||
process.exit(1); | ||
} | ||
}; | ||
|
||
const execute = ({ input, options }: { input: MultiLine; options?: Settings }) => { | ||
withError(() => { | ||
const output = plot(input, options); | ||
process.stdout.write(output); | ||
process.exit(0); | ||
}); | ||
}; | ||
|
||
const prepareParams = ({ | ||
input, | ||
options, | ||
width, | ||
height, | ||
hideYAxis, | ||
hideXAxis, | ||
fillArea, | ||
title, | ||
xLabel, | ||
yLabel, | ||
color, | ||
axisCenter, | ||
}: { | ||
input: string; | ||
options?: string; | ||
title?: string; | ||
xLabel?: string; | ||
yLabel?: string; | ||
width?: number; | ||
height?: number; | ||
fillArea?: boolean; | ||
hideYAxis?: boolean; | ||
hideXAxis?: boolean; | ||
color?: (string | number)[]; | ||
axisCenter?: (string | number)[]; | ||
}) => { | ||
const currentOptions = options ? JSON.parse(options) : {}; | ||
|
||
return { | ||
input: JSON.parse(input) as MultiLine, | ||
options: { | ||
...currentOptions, | ||
width, | ||
height, | ||
hideYAxis, | ||
hideXAxis, | ||
title, | ||
xLabel, | ||
yLabel, | ||
fillArea, | ||
color, | ||
axisCenter, | ||
}, | ||
}; | ||
}; | ||
|
||
if (argv instanceof Promise) { | ||
argv.then((parameters) => { | ||
withError(() => { | ||
execute(prepareParams(parameters)); | ||
}); | ||
}); | ||
} else { | ||
withError(() => { | ||
execute(prepareParams(argv)); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
import { getSymbols, getLabelShift, getInput, getChartSize } from '../defaults'; | ||
import { AXIS, EMPTY } from '../../constants'; | ||
import { Coordinates, MultiLine } from '../../types'; | ||
|
||
describe('Chart Helper Functions', () => { | ||
describe('getSymbols', () => { | ||
it('should return default symbols when none are provided', () => { | ||
const symbols = getSymbols({}); | ||
expect(symbols).toEqual({ | ||
axisSymbols: AXIS, | ||
emptySymbol: EMPTY, | ||
backgroundSymbol: EMPTY, | ||
borderSymbol: undefined, | ||
}); | ||
}); | ||
|
||
it('should override default symbols when provided', () => { | ||
const customSymbols = { | ||
axis: { x: 'X', y: 'Y' }, | ||
empty: '-', | ||
background: '=', | ||
border: '#', | ||
}; | ||
const symbols = getSymbols({ symbols: customSymbols }); | ||
expect(symbols).toEqual({ | ||
axisSymbols: { ...AXIS, ...customSymbols.axis }, | ||
emptySymbol: customSymbols.empty, | ||
backgroundSymbol: customSymbols.background, | ||
borderSymbol: customSymbols.border, | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getChartSize', () => { | ||
it('should return default sizes when width and height are not provided', () => { | ||
const input: MultiLine = [ | ||
[ | ||
[1, 2], | ||
[2, 4], | ||
[3, 6], | ||
], | ||
]; | ||
const size = getChartSize({ input }); | ||
expect(size).toEqual({ | ||
minX: 1, | ||
plotWidth: 3, // length of rangeX | ||
plotHeight: 5, // maxY - minY + 1 | ||
expansionX: [1, 3], | ||
expansionY: [2, 6], | ||
}); | ||
}); | ||
|
||
it('should use provided width and height', () => { | ||
const input: MultiLine = [ | ||
[ | ||
[1, 2], | ||
[2, 4], | ||
[3, 6], | ||
], | ||
]; | ||
|
||
const size = getChartSize({ input, width: 10, height: 10 }); | ||
expect(size).toEqual({ | ||
minX: 1, | ||
plotWidth: 10, | ||
plotHeight: 10, | ||
expansionX: [1, 3], | ||
expansionY: [2, 6], | ||
}); | ||
}); | ||
|
||
it('should adjust for small values without height', () => { | ||
const input: MultiLine = [ | ||
[ | ||
[1, 2], | ||
[2, 4], | ||
], | ||
]; | ||
const size = getChartSize({ input }); | ||
expect(size).toEqual({ | ||
minX: 1, | ||
plotWidth: 2, // length of rangeX | ||
plotHeight: 3, // length of rangeY since it's less than 3 without provided height | ||
expansionX: [1, 2], | ||
expansionY: [2, 4], | ||
}); | ||
}); | ||
|
||
it('should handle a mix of positive and negative values', () => { | ||
const input: MultiLine = [ | ||
[ | ||
[-3, -2], | ||
[-2, 4], | ||
[0, 0], | ||
[3, -1], | ||
], | ||
]; | ||
const size = getChartSize({ input }); | ||
expect(size).toEqual({ | ||
minX: -3, | ||
plotWidth: 4, // length of rangeX | ||
plotHeight: 7, // maxY - minY + 1 | ||
expansionX: [-3, 3], | ||
expansionY: [-2, 4], | ||
}); | ||
}); | ||
}); | ||
|
||
describe('getLabelShift', () => { | ||
it('should calculate label shifts correctly', () => { | ||
const input: MultiLine = [ | ||
[ | ||
[1, 2], | ||
[3, 4], | ||
[5, 6], | ||
], | ||
]; | ||
const transformLabel = (value: number) => value.toString(); | ||
const result = getLabelShift({ | ||
input, | ||
transformLabel, | ||
expansionX: [1, 5], | ||
expansionY: [2, 6], | ||
minX: 1, | ||
}); | ||
|
||
expect(result.xShift).toBe(1); | ||
expect(result.yShift).toBe(1); | ||
}); | ||
}); | ||
|
||
describe('getInput', () => { | ||
it('should convert singleline input to multiline', () => { | ||
const input: Coordinates = [ | ||
[1, 2], | ||
[3, 4], | ||
]; | ||
const result = getInput({ rawInput: input }); | ||
expect(result).toEqual([input]); | ||
}); | ||
|
||
it('should keep multiline input unchanged', () => { | ||
const input: MultiLine = [ | ||
[ | ||
[1, 2], | ||
[3, 4], | ||
], | ||
[ | ||
[5, 6], | ||
[7, 8], | ||
], | ||
]; | ||
const result = getInput({ rawInput: input }); | ||
expect(result).toEqual(input); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.