diff --git a/src/assert.js b/src/assert.js index 35ea290..916fa81 100644 --- a/src/assert.js +++ b/src/assert.js @@ -44,7 +44,7 @@ const _in = exports.in = (raw, name, arr) => { const arr = exports.arr = (raw, name, length, _type, _default) => units => { assert(type(raw)(units) == 'array', `Field "${name}" should be an array!`) assert(length == 0 || raw.length == length, `Field "${name}" should be an array of length ${length}!`) - raw = raw.map(val => val || _default) + raw = raw.map(val => val === undefined ? _default : val) raw.map(val => assert(type(val)(units) == _type, `Field "${name}" should contain ${_type}s!`)) if (_type == 'number') { raw = raw.map(val => mathnum(val)(units)) @@ -62,8 +62,8 @@ const wh = exports.wh = (raw, name) => units => { return xy(raw, name)(units) } -exports.trbl = (raw, name) => units => { +exports.trbl = (raw, name, _default=0) => units => { if (!Array.isArray(raw)) raw = [raw, raw, raw, raw] if (raw.length == 2) raw = [raw[1], raw[0], raw[1], raw[0]] - return numarr(raw, name, 4, 'number', 0)(units) + return arr(raw, name, 4, 'number', _default)(units) } diff --git a/src/outlines.js b/src/outlines.js index 66e0849..ed1061f 100644 --- a/src/outlines.js +++ b/src/outlines.js @@ -198,8 +198,7 @@ exports.parse = (config = {}, points = {}, units = {}) => { // process keys that are common to all part declarations const operation = u[a.in(part.operation || 'add', `${name}.operation`, ['add', 'subtract', 'intersect', 'stack'])] const what = a.in(part.what || 'outline', `${name}.what`, ['rectangle', 'circle', 'polygon', 'outline']) - const bound_by_default = ['rectangle'] - const bound = part.bound === undefined ? bound_by_default.includes(what) : !!part.bound + const bound = !!part.bound const mirror = a.sane(part.mirror || false, `${name}.mirror`, 'boolean')() // `where` is delayed until we have all, potentially what-dependent units // default where is [0, 0], as per filter parsing diff --git a/src/points.js b/src/points.js index 5f6c0c0..0d48cc8 100644 --- a/src/points.js +++ b/src/points.js @@ -43,6 +43,7 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key, // column layout + const col_minmax = {} if (!Object.keys(cols).length) { cols.default = {} } @@ -52,6 +53,7 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key, // column-level sanitization col = col || {} + col_minmax[col_name] = {min: Infinity, max: -Infinity} a.unexpected( col, @@ -93,6 +95,7 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key, width: units.$default_width, height: units.$default_height, padding: units.$default_padding, + autobind: units.$default_autobind, skip: false, asym: 'both', colrow: '{{col.name}}_{{row}}', @@ -155,21 +158,83 @@ const render_zone = exports._render_zone = (zone_name, zone, anchor, global_key, // actually laying out keys for (const key of keys) { + + // copy the current column anchor let point = col_anchor.clone() + + // apply transformations for (const r of rotations) { point.rotate(r.angle, r.origin) } point.r += key.orient point.shift(key.shift) point.r += key.rotate + + // save new key point.meta = key points[key.name] = point + + // collect minmax stats for autobind + col_minmax[col_name].min = Math.min(col_minmax[col_name].min, point.y) + col_minmax[col_name].max = Math.max(col_minmax[col_name].max, point.y) + + // advance the column anchor to the next position col_anchor.y += key.padding } first_col = false } + // autobind + + let col_names = Object.keys(col_minmax) + let col_index = 0 + for (const [col_name, bounds] of Object.entries(col_minmax)) { + for (const point of Object.values(points)) { + if (point.meta.col.name != col_name) continue + if (!point.meta.autobind) continue + const autobind = a.sane(point.meta.autobind, `${point.meta.name}.autobind`, 'number')(units) + // specify default as -1, so we can recognize where it was left undefined even after number-ification + const bind = point.meta.bind = a.trbl(point.meta.bind, `${point.meta.name}.bind`, -1)(units) + + // up + if (bind[0] == -1) { + if (point.y < bounds.max) bind[0] = autobind + else bind[0] = 0 + + } + + // right + if (bind[1] == -1) { + bind[1] = 0 + if (col_index < col_names.length - 1) { + const right = col_minmax[col_names[col_index + 1]] + if (point.y >= right.min && point.y <= right.max) { + bind[1] = autobind + } + } + } + + // down + if (bind[2] == -1) { + if (point.y > bounds.min) bind[2] = autobind + else bind[2] = 0 + } + + // left + if (bind[3] == -1) { + bind[3] = 0 + if (col_index > 0) { + const left = col_minmax[col_names[col_index - 1]] + if (point.y >= left.min && point.y <= left.max) { + bind[3] = autobind + } + } + } + } + col_index++ + } + return points } diff --git a/src/units.js b/src/units.js index 90e0eaa..6831192 100644 --- a/src/units.js +++ b/src/units.js @@ -11,7 +11,8 @@ const default_units = { $default_splay: 0, $default_height: 'u-1', $default_width: 'u-1', - $default_padding: 'u' + $default_padding: 'u', + $default_autobind: 10 } exports.parse = (config = {}) => { diff --git a/test/cli/bad_input/error b/test/cli/bad_input/error index 2ed6722..e922a13 100644 --- a/test/cli/bad_input/error +++ b/test/cli/bad_input/error @@ -1 +1 @@ -Error: Input doesn't resolve into an object! +Error: Input doesn't resolve into an object! \ No newline at end of file diff --git a/test/cli/big/reference/points/points.yaml b/test/cli/big/reference/points/points.yaml index 82720d6..f744193 100644 --- a/test/cli/big/reference/points/points.yaml +++ b/test/cli/big/reference/points/points.yaml @@ -17,6 +17,7 @@ matrix: width: 18 height: 18 padding: 19 + autobind: 10 skip: false asym: both colrow: default_default @@ -28,3 +29,8 @@ matrix: key: {} name: default row: default + bind: + - 0 + - 0 + - 0 + - 0 diff --git a/test/cli/big/reference/points/units.yaml b/test/cli/big/reference/points/units.yaml index ae049c1..0b00ed1 100644 --- a/test/cli/big/reference/points/units.yaml +++ b/test/cli/big/reference/points/units.yaml @@ -8,4 +8,5 @@ $default_splay: 0 $default_height: 18 $default_width: 18 $default_padding: 19 +$default_autobind: 10 a: 47 diff --git a/test/cli/minimal/reference/points/points.yaml b/test/cli/minimal/reference/points/points.yaml index a3179f0..0ec0976 100644 --- a/test/cli/minimal/reference/points/points.yaml +++ b/test/cli/minimal/reference/points/points.yaml @@ -17,6 +17,7 @@ matrix_col_row: width: 18 height: 18 padding: 19 + autobind: 10 skip: false asym: both colrow: col_row @@ -32,3 +33,8 @@ matrix_col_row: name: matrix col: *ref_0 row: row + bind: + - 0 + - 0 + - 0 + - 0 diff --git a/test/cli/minimal/reference/points/units.yaml b/test/cli/minimal/reference/points/units.yaml index 4f4cee3..454b8bb 100644 --- a/test/cli/minimal/reference/points/units.yaml +++ b/test/cli/minimal/reference/points/units.yaml @@ -8,3 +8,4 @@ $default_splay: 0 $default_height: 18 $default_width: 18 $default_padding: 19 +$default_autobind: 10 diff --git a/test/cli/missing_input/error b/test/cli/missing_input/error index 8948ed0..2b2dba0 100644 --- a/test/cli/missing_input/error +++ b/test/cli/missing_input/error @@ -1 +1 @@ -Usage: ergogen [options] +Usage: ergogen [options] \ No newline at end of file diff --git a/test/cli/nonexistent_input/error b/test/cli/nonexistent_input/error index d5ef9b2..4207ee3 100644 --- a/test/cli/nonexistent_input/error +++ b/test/cli/nonexistent_input/error @@ -1 +1 @@ -Could not read config file "nonexistent.yaml": Error: ENOENT: no such file or directory, open 'nonexistent.yaml' +Could not read config file "nonexistent.yaml": Error: ENOENT: no such file or directory, open 'nonexistent.yaml' \ No newline at end of file diff --git a/test/outlines/fillet.yaml b/test/outlines/fillet.yaml index a34ed68..5dc5e85 100644 --- a/test/outlines/fillet.yaml +++ b/test/outlines/fillet.yaml @@ -15,6 +15,7 @@ outlines: - what: rectangle where: true size: cy + bound: true fillet: - what: outline name: base diff --git a/test/points/adjustments___points.json b/test/points/adjustments___points.json index 25ce5c1..ab5e160 100644 --- a/test/points/adjustments___points.json +++ b/test/points/adjustments___points.json @@ -20,6 +20,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "left_bottom", @@ -61,7 +62,13 @@ "key": {}, "name": "left" }, - "row": "bottom" + "row": "bottom", + "bind": [ + 10, + 0, + 0, + 0 + ] } }, "matrix_left_top": { @@ -85,6 +92,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "left_top", @@ -126,7 +134,13 @@ "key": {}, "name": "left" }, - "row": "top" + "row": "top", + "bind": [ + 0, + 10, + 10, + 0 + ] } }, "matrix_right_bottom": { @@ -150,6 +164,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "right_bottom", @@ -208,7 +223,13 @@ }, "name": "right" }, - "row": "bottom" + "row": "bottom", + "bind": [ + 10, + 0, + 0, + 10 + ] } }, "matrix_right_top": { @@ -232,6 +253,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "right_top", @@ -290,7 +312,13 @@ }, "name": "right" }, - "row": "top" + "row": "top", + "bind": [ + 0, + 0, + 10, + 0 + ] } } } diff --git a/test/points/basic_2x2___points.json b/test/points/basic_2x2___points.json index d2c7baf..ab42f3d 100644 --- a/test/points/basic_2x2___points.json +++ b/test/points/basic_2x2___points.json @@ -20,6 +20,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "left_bottom", @@ -40,7 +41,13 @@ "key": {}, "name": "left" }, - "row": "bottom" + "row": "bottom", + "bind": [ + 10, + 10, + 0, + 0 + ] } }, "matrix_left_top": { @@ -64,6 +71,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "left_top", @@ -84,7 +92,13 @@ "key": {}, "name": "left" }, - "row": "top" + "row": "top", + "bind": [ + 0, + 10, + 10, + 0 + ] } }, "matrix_right_bottom": { @@ -108,6 +122,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "right_bottom", @@ -128,7 +143,13 @@ "key": {}, "name": "right" }, - "row": "bottom" + "row": "bottom", + "bind": [ + 10, + 0, + 0, + 10 + ] } }, "matrix_right_top": { @@ -152,6 +173,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "right_top", @@ -172,7 +194,13 @@ "key": {}, "name": "right" }, - "row": "top" + "row": "top", + "bind": [ + 0, + 0, + 10, + 10 + ] } } } diff --git a/test/points/default___points.json b/test/points/default___points.json index d1c34cb..667bfc4 100644 --- a/test/points/default___points.json +++ b/test/points/default___points.json @@ -20,6 +20,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "default_default", @@ -32,7 +33,13 @@ "key": {}, "name": "default" }, - "row": "default" + "row": "default", + "bind": [ + 0, + 0, + 0, + 0 + ] } } } diff --git a/test/points/overrides___points.json b/test/points/overrides___points.json index 6edfefd..9094335 100644 --- a/test/points/overrides___points.json +++ b/test/points/overrides___points.json @@ -20,6 +20,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "left_bottom", @@ -57,7 +58,13 @@ "key": {}, "name": "left" }, - "row": "bottom" + "row": "bottom", + "bind": [ + 10, + 10, + 0, + 0 + ] } }, "matrix_left_home": { @@ -81,6 +88,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "left_home", @@ -118,7 +126,13 @@ "key": {}, "name": "left" }, - "row": "home" + "row": "home", + "bind": [ + 0, + 10, + 10, + 0 + ] } }, "matrix_middle_bottom": { @@ -142,6 +156,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "middle_bottom", @@ -181,7 +196,13 @@ "key": {}, "name": "middle" }, - "row": "bottom" + "row": "bottom", + "bind": [ + 10, + 0, + 0, + 10 + ] } }, "matrix_middle_home": { @@ -205,6 +226,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "middle_home", @@ -244,7 +266,13 @@ "key": {}, "name": "middle" }, - "row": "home" + "row": "home", + "bind": [ + 10, + 10, + 10, + 10 + ] } }, "matrix_middle_top": { @@ -268,6 +296,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "middle_top", @@ -307,7 +336,13 @@ "key": {}, "name": "middle" }, - "row": "top" + "row": "top", + "bind": [ + 0, + 10, + 10, + 0 + ] } }, "matrix_right_home": { @@ -331,6 +366,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "right_home", @@ -374,7 +410,13 @@ }, "name": "right" }, - "row": "home" + "row": "home", + "bind": [ + 10, + 0, + 0, + 10 + ] } }, "matrix_right_top": { @@ -398,6 +440,7 @@ "width": 18, "height": 18, "padding": 19, + "autobind": 10, "skip": false, "asym": "both", "colrow": "right_top", @@ -441,7 +484,13 @@ }, "name": "right" }, - "row": "top" + "row": "top", + "bind": [ + 0, + 0, + 10, + 10 + ] } } } diff --git a/test/points/units___units.json b/test/points/units___units.json index 729b66e..07b55ed 100644 --- a/test/points/units___units.json +++ b/test/points/units___units.json @@ -3,12 +3,13 @@ "u": 19, "cx": 18, "cy": 17, - "a": 10, - "b": 15, "$default_stagger": 0, "$default_spread": 19, "$default_splay": 0, "$default_height": 18, "$default_width": 18, - "$default_padding": 19 + "$default_padding": 19, + "$default_autobind": 10, + "a": 10, + "b": 15 }