Skip to content

Commit

Permalink
Allow client to get the current scroll position and an array with the…
Browse files Browse the repository at this point in the history
… split content (#6)

* rename private fields with _ prefix

* add getters

* add tests for the new getters

* improve jsdoc description
  • Loading branch information
pawap90 authored Apr 23, 2024
1 parent 2a1edfc commit 78fa334
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 11 deletions.
31 changes: 23 additions & 8 deletions src/scrollable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ export type ScrollableOptions = {
* A scrollable area that can be printed to the console.
*/
export class Scrollable {
private lines: string[] = [];
private currentLine = 0;
private _lines: string[] = [];
private _position = 0;
private _options: ScrollableOptions;

/**
Expand All @@ -51,6 +51,21 @@ export class Scrollable {
return this._options;
}

/**
* The lines of content in the scrollable area
* wrapped according to the specified {@link ScrollableOptions} and split into an array of lines.
*/
get lines(): string[] {
return this._lines;
}

/**
* The position of the first line to display in the scrollable area.
*/
get position(): number {
return this._position;
}

/**
* Creates a new Scrollable instance.
* @param options - The options for the Scrollable instance.
Expand Down Expand Up @@ -130,7 +145,7 @@ export class Scrollable {
* @returns The Scrollable instance.
*/
print(): this {
if (this.lines.length == 0) this.splitContentIntoLines();
if (this._lines.length == 0) this.splitContentIntoLines();
const { x, y } = this._options.start;
const { width, height } = this._options.size;
const emptyLine = Array(width).fill(' ').join('');
Expand All @@ -141,7 +156,7 @@ export class Scrollable {

stdout.cursorTo(x, y);
for (let i = 0; i < height; i++) {
const line = this.lines[i + this.currentLine];
const line = this._lines[i + this._position];
stdout.cursorTo(x);

stdout.write((line ?? emptyLine) + '\n');
Expand All @@ -156,7 +171,7 @@ export class Scrollable {
* @returns The Scrollable instance.
*/
scroll(lines: number): this {
this.currentLine += lines;
this._position += lines;
return this;
}

Expand All @@ -180,8 +195,8 @@ export class Scrollable {
}

private resetLines(): void {
this.lines = [];
this.currentLine = 0;
this._lines = [];
this._position = 0;
}

private splitContentIntoLines(): void {
Expand All @@ -192,6 +207,6 @@ export class Scrollable {
this._options.size.width,
this._options.wrapOptions
);
this.lines = wrapped.split('\n');
this._lines = wrapped.split('\n');
}
}
70 changes: 67 additions & 3 deletions tests/scrollable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,70 @@ describe('Scrollable', () => {
scrollable = new Scrollable({ stdout: createFakeStdout() });
});

describe('get position', () => {
it('should return the current position of the scrollable area', () => {
scrollable.setContent(
'Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod'
);

scrollable.scroll(1);
expect(scrollable.position).to.equal(1);

scrollable.scroll(-2);
expect(scrollable.position).to.equal(-1);

scrollable.scroll(5);
expect(scrollable.position).to.equal(4);
});
});

describe('get lines', () => {
it('should return all the lines of the content in an array', () => {
scrollable
.setContent('Lorem ipsum dolor sit amet consectetur adipiscing elit sed do eiusmod')
.setSize({ width: 12, height: 3 })
.print();

expect(scrollable.lines).to.be.an('array').that.has.lengthOf(7);
expect(scrollable.lines[0]).to.equal('Lorem ipsum');
expect(scrollable.lines[1]).to.equal('dolor sit');
expect(scrollable.lines[2]).to.equal('amet');
expect(scrollable.lines[3]).to.equal('consectetur');
expect(scrollable.lines[4]).to.equal('adipiscing');
expect(scrollable.lines[5]).to.equal('elit sed do');
expect(scrollable.lines[6]).to.equal('eiusmod');
});

it('should return all the lines of the content in an array considering newlines', () => {
scrollable
.setContent('Lorem \nipsum dolor sit\n amet consectetur')
.setSize({ width: 12, height: 3 })
.print();

expect(scrollable.lines).to.be.an('array').that.has.lengthOf(5);
expect(scrollable.lines[0]).to.equal('Lorem');
expect(scrollable.lines[1]).to.equal('ipsum dolor');
expect(scrollable.lines[2]).to.equal('sit');
expect(scrollable.lines[3]).to.equal('amet');
expect(scrollable.lines[4]).to.equal('consectetur');
});

it('should return all the lines of the content after scrolling', () => {
scrollable
.setContent('Lorem ipsum dolor sit amet consectetur')
.setSize({ width: 12, height: 3 })
.print();

scrollable.scroll(4);

expect(scrollable.lines).to.be.an('array').that.has.lengthOf(4);
expect(scrollable.lines[0]).to.equal('Lorem ipsum');
expect(scrollable.lines[1]).to.equal('dolor sit');
expect(scrollable.lines[2]).to.equal('amet');
expect(scrollable.lines[3]).to.equal('consectetur');
});
});

describe('print', () => {
let spyWrite: SinonSpy;

Expand Down Expand Up @@ -100,13 +164,13 @@ describe('Scrollable', () => {
);

scrollable.scroll(1);
expect(scrollable['currentLine']).to.equal(1);
expect(scrollable['_position']).to.equal(1);

scrollable.scroll(-2);
expect(scrollable['currentLine']).to.equal(-1);
expect(scrollable['_position']).to.equal(-1);

scrollable.scroll(5);
expect(scrollable['currentLine']).to.equal(4);
expect(scrollable['_position']).to.equal(4);
});

it('should print the correct lines after scrolling down', () => {
Expand Down

0 comments on commit 78fa334

Please sign in to comment.