1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 17:58:12 +00:00

Spreadsheet: Let the cells know their own position in the sheet

This commit is contained in:
AnotherTest 2020-09-26 15:29:11 +03:30 committed by Andreas Kling
parent 13ce24de13
commit f159d161fa
7 changed files with 227 additions and 22 deletions

View file

@ -1,8 +1,82 @@
// FIXME: Figure out a way to document non-function entities too.
class Position {
constructor(column, row, sheet) {
this.column = column;
this.row = row;
this.sheet = sheet ?? thisSheet;
this.name = `${column}${row}`;
}
static from_name(name) {
let sheet = thisSheet;
let obj = sheet.parse_cell_name(name);
return new Position(obj.column, obj.row, sheet);
}
up(how_many) {
how_many = how_many ?? 1;
const row = Math.max(0, this.row - how_many);
return new Position(this.column, row, this.sheet);
}
down(how_many) {
how_many = how_many ?? 1;
const row = Math.max(0, this.row + how_many);
return new Position(this.column, row, this.sheet);
}
left(how_many) {
how_many = how_many ?? 1;
const column = Math.min(
"Z".charCodeAt(0),
Math.max("A".charCodeAt(0), this.column.charCodeAt(0) - how_many)
);
return new Position(String.fromCharCode(column), this.row, this.sheet);
}
right(how_many) {
how_many = how_many ?? 1;
const column = Math.min(
"Z".charCodeAt(0),
Math.max("A".charCodeAt(0), this.column.charCodeAt(0) + how_many)
);
return new Position(String.fromCharCode(column), this.row, this.sheet);
}
with_column(value) {
return new Position(value, this.row, this.sheet);
}
with_row(value) {
return new Position(this.column, value, this.sheet);
}
in_sheet(the_sheet) {
return new Position(this.column, this.row, sheet(the_sheet));
}
value() {
return this.sheet[this.name];
}
valueOf() {
return value();
}
toString() {
return `<Cell at ${this.name}>`;
}
}
function range(start, end, columnStep, rowStep) {
columnStep = integer(columnStep ?? 1);
rowStep = integer(rowStep ?? 1);
start = parse_cell_name(start) ?? { column: "A", row: 0 };
end = parse_cell_name(end) ?? start;
if (!(start instanceof Position)) {
start = parse_cell_name(start) ?? { column: "A", row: 0 };
}
if (!(end instanceof Position)) {
end = parse_cell_name(end) ?? start;
}
if (end.column.length > 1 || start.column.length > 1)
throw new TypeError("Only single-letter column names are allowed (TODO)");
@ -172,6 +246,21 @@ function stddev(cells) {
return Math.sqrt(variance(cells));
}
// Lookup
function row() {
return thisSheet.current_cell_position().row;
}
function column() {
return thisSheet.current_cell_position().column;
}
function here() {
const position = current_cell_position();
return new Position(position.column, position.row, thisSheet);
}
// Cheat the system and add documentation
range.__documentation = JSON.stringify({
name: "range",
@ -382,3 +471,42 @@ stddev.__documentation = JSON.stringify({
'stddev(range("A0", "C4"))': "Calculate the standard deviation of the values in A0:C4",
},
});
row.__documentation = JSON.stringify({
name: "row",
argc: 0,
argnames: [],
doc: "Returns the row number of the current cell",
examples: {},
});
column.__documentation = JSON.stringify({
name: "column",
argc: 0,
argnames: [],
doc: "Returns the column name of the current cell",
examples: {},
});
here.__documentation = JSON.stringify({
name: "here",
argc: 0,
argnames: [],
doc:
"Returns an object representing the current cell's position, see `Position` below.\n\n" +
"## Position\na `Position` is an object representing a given cell position in a given sheet.\n" +
"### Methods:\n- `up(count = 1)`: goes up count cells, or returns the top position if at the top\n" +
"- `down(count = 1)`: goes down count cells\n" +
"- `left(count = 1)`: Goes left count cells, or returns the leftmost position if the edge\n" +
"- `right(count = 1)`: Goes right count cells.\n" +
"- `with_row(row)`: Returns a Position with its column being this object's, and its row being the provided the value.\n" +
"- `with_column(column)`: Similar to `with_row()`, but changes the column instead.\n" +
"- `in_sheet(the_sheet)`: Returns a Position with the same column and row as this one, but with its sheet being `the_sheet`.\n" +
"- `value()`: Returns the value at the position which it represents, in the object's sheet (current sheet by default).\n\n" +
"**NOTE**: Currently only supports single-letter column names",
examples: {
"here().up().value()": "Get the value of the cell above this one",
"here().up().with_column('A')":
"Get a Position above this one in column A, for instance, evaluates to A2 if run in B3.",
},
});