mirror of
https://github.com/Automattic/harper.git
synced 2025-12-23 08:48:15 +00:00
feat: just printaffixes prints letters free for new flags (#1540)
* feat: `just printaffixes` prints letters free for new flags I've also renamed it to `just annotations` but kept the old name as an alias. Annotations that have comment fields will also be in the printout now. * fix: remove comment * feat: `suggestannotation` Pass in a term you want to make a new annotation for and it will check if any of the letters are not already used, or are OK to reuse.
This commit is contained in:
parent
f612cf1c33
commit
ffc88736cf
2 changed files with 98 additions and 17 deletions
|
|
@ -12,7 +12,8 @@
|
|||
}
|
||||
],
|
||||
"target": [],
|
||||
"base_metadata": {}
|
||||
"base_metadata": {},
|
||||
"rename_ok": true
|
||||
},
|
||||
"L": {
|
||||
"#": "'-ment' suffix",
|
||||
|
|
@ -26,7 +27,8 @@
|
|||
}
|
||||
],
|
||||
"target": [],
|
||||
"base_metadata": {}
|
||||
"base_metadata": {},
|
||||
"rename_ok": true
|
||||
},
|
||||
"E": {
|
||||
"#": "'dis-' prefix",
|
||||
|
|
@ -40,7 +42,8 @@
|
|||
}
|
||||
],
|
||||
"target": [],
|
||||
"base_metadata": {}
|
||||
"base_metadata": {},
|
||||
"rename_ok": true
|
||||
},
|
||||
"Y": {
|
||||
"#": "'-ly' suffix",
|
||||
|
|
@ -259,7 +262,8 @@
|
|||
}
|
||||
],
|
||||
"target": [],
|
||||
"base_metadata": {}
|
||||
"base_metadata": {},
|
||||
"rename_ok": true
|
||||
},
|
||||
"p": {
|
||||
"#": "'-(i)ness' suffix",
|
||||
|
|
@ -283,10 +287,12 @@
|
|||
}
|
||||
],
|
||||
"target": [],
|
||||
"base_metadata": {}
|
||||
"base_metadata": {},
|
||||
"rename_ok": true
|
||||
},
|
||||
"g": {
|
||||
"#": "-'s possessive suffix; contraction of 'has' and 'is",
|
||||
"//": "mnemonic: 'genitive' is a similar concept to 'possessive'",
|
||||
"kind": "suffix",
|
||||
"cross_product": true,
|
||||
"replacements": [
|
||||
|
|
@ -321,7 +327,8 @@
|
|||
}
|
||||
],
|
||||
"target": [],
|
||||
"base_metadata": {}
|
||||
"base_metadata": {},
|
||||
"rename_ok": true
|
||||
},
|
||||
"B": {
|
||||
"#": "'-able' suffix",
|
||||
|
|
@ -481,7 +488,8 @@
|
|||
}
|
||||
],
|
||||
"target": [],
|
||||
"base_metadata": {}
|
||||
"base_metadata": {},
|
||||
"rename_ok": true
|
||||
},
|
||||
"f": {
|
||||
"#": "'-ful' suffix",
|
||||
|
|
@ -533,7 +541,8 @@
|
|||
}
|
||||
],
|
||||
"target": [],
|
||||
"base_metadata": {}
|
||||
"base_metadata": {},
|
||||
"rename_ok": true
|
||||
},
|
||||
"z": {
|
||||
"#": "'-ings' suffix",
|
||||
|
|
@ -552,7 +561,8 @@
|
|||
}
|
||||
],
|
||||
"target": [],
|
||||
"base_metadata": {}
|
||||
"base_metadata": {},
|
||||
"rename_ok": true
|
||||
}
|
||||
},
|
||||
"properties": {
|
||||
|
|
@ -593,6 +603,7 @@
|
|||
},
|
||||
"x": {
|
||||
"#": "swear word property",
|
||||
"//": "'xxx' used to be a placeholder for swear words",
|
||||
"propagate": true,
|
||||
"metadata": {
|
||||
"swear": true
|
||||
|
|
@ -632,7 +643,8 @@
|
|||
"#": "common word property",
|
||||
"metadata": {
|
||||
"common": true
|
||||
}
|
||||
},
|
||||
"rename_ok": true
|
||||
},
|
||||
"P": {
|
||||
"#": "preposition property",
|
||||
|
|
@ -716,6 +728,7 @@
|
|||
},
|
||||
".": {
|
||||
"#": "singular pronoun property",
|
||||
"//": "mnemonic: one dot",
|
||||
"metadata": {
|
||||
"pronoun": {
|
||||
"is_singular": true
|
||||
|
|
@ -724,6 +737,7 @@
|
|||
},
|
||||
":": {
|
||||
"#": "plural pronoun property",
|
||||
"//": "mnemonic: multiple dots",
|
||||
"metadata": {
|
||||
"pronoun": {
|
||||
"is_plural": true
|
||||
|
|
@ -744,17 +758,20 @@
|
|||
"propagate": true,
|
||||
"metadata": {
|
||||
"dialects": "AMERICAN"
|
||||
}
|
||||
},
|
||||
"rename_ok": true
|
||||
},
|
||||
"!": {
|
||||
"#": "GB property",
|
||||
"propagate": true,
|
||||
"metadata": {
|
||||
"dialects": "BRITISH"
|
||||
}
|
||||
},
|
||||
"rename_ok": true
|
||||
},
|
||||
"@": {
|
||||
"#": "CA property",
|
||||
"//": "mnemonic: at symbol resembles an 'a' inside a 'C'",
|
||||
"propagate": true,
|
||||
"metadata": {
|
||||
"dialects": "CANADIAN"
|
||||
|
|
@ -762,6 +779,7 @@
|
|||
},
|
||||
"_": {
|
||||
"#": "AU property",
|
||||
"//": "mnemonic: down under",
|
||||
"propagate": true,
|
||||
"metadata": {
|
||||
"dialects": "AUSTRALIAN"
|
||||
|
|
@ -785,6 +803,7 @@
|
|||
},
|
||||
"5": {
|
||||
"#": "possessive determiner property",
|
||||
"//": "mnemonic: 5 looks like an 's'",
|
||||
"metadata": {
|
||||
"determiner": {
|
||||
"is_possessive": true
|
||||
|
|
|
|||
72
justfile
72
justfile
|
|
@ -438,19 +438,39 @@ registerlinter module name:
|
|||
sed -i "/insert_expr_rule!(ChockFull, true);/a \ \ \ \ insert_struct_rule!({{name}}, true);" "$D/lint_group.rs"
|
||||
just format
|
||||
|
||||
# Print affixes and their descriptions from annotations.json
|
||||
printaffixes:
|
||||
# Print annotations and their descriptions from annotations.json
|
||||
alias printaffixes := printannotations
|
||||
|
||||
printannotations:
|
||||
#! /usr/bin/env node
|
||||
const affixesData = require('{{justfile_directory()}}/harper-core/annotations.json');
|
||||
const allAffixes = {
|
||||
const allEntries = {
|
||||
...affixesData.affixes || {},
|
||||
...affixesData.properties || {}
|
||||
};
|
||||
Object.entries(allAffixes).sort((a, b) => a[0].localeCompare(b[0])).forEach(([affix, fields]) => {
|
||||
Object.entries(allEntries).sort((a, b) => a[0].localeCompare(b[0])).forEach(([flag, fields]) => {
|
||||
const description = fields['#'] || '';
|
||||
description && console.log(affix + ': ' + description);
|
||||
const comment = fields['//'] || null;
|
||||
description && console.log(flag + ': ' + description + (comment ? '\t\t// ' + comment : ''));
|
||||
});
|
||||
|
||||
console.log('Available letters for new flags:', [...Array.from({length: 26}, (_, i) =>
|
||||
[String.fromCharCode(65 + i), String.fromCharCode(97 + i)]
|
||||
).flat()].filter(letter => !Object.keys(allEntries).includes(letter)).sort().join(' '));
|
||||
console.log('Available digits for new flags:', [...Array.from({length: 10}, (_, i) =>
|
||||
String(i)
|
||||
)].filter(digit => !Object.keys(allEntries).includes(digit)).sort().join(' '));
|
||||
console.log('Available symbols for new flags:',
|
||||
[...Array.from('!"#$%&\'()*+,-./:;<=>?@\[\\\]\^_`{|}~')]
|
||||
.filter(symbol => !Object.keys(allEntries).includes(symbol)).sort().join(' '));
|
||||
console.log('Available Latin-1 characters for new flags:');
|
||||
[...Array.from({length: 256-160}, (_, i) => String.fromCharCode(160 + i))]
|
||||
.filter(char => !Object.keys(allEntries).includes(char) && char.charCodeAt(0) !== 160 && char.charCodeAt(0) !== 173)
|
||||
.sort()
|
||||
.join(' ')
|
||||
.match(/.{1,64}/g)
|
||||
.forEach(line => console.log(' ' + line));
|
||||
|
||||
# Get the most recent changes to the curated dictionary. Includes an optional argument to specify the number of commits to look back. Defaults to 1.
|
||||
newest-dict-changes *numCommits:
|
||||
#! /usr/bin/env node
|
||||
|
|
@ -553,3 +573,45 @@ newest-dict-changes *numCommits:
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
# Suggest annotations for a potential new property annotation
|
||||
suggestannotation input:
|
||||
#! /usr/bin/env node
|
||||
const affixesData = require('{{justfile_directory()}}/harper-core/annotations.json');
|
||||
const allEntries = {
|
||||
...affixesData.affixes || {},
|
||||
...affixesData.properties || {}
|
||||
};
|
||||
|
||||
// Get all used flags
|
||||
const usedFlags = new Set(Object.keys(allEntries));
|
||||
|
||||
// Process input string and check both cases
|
||||
const input = '{{input}}';
|
||||
const normalizedInput = input.replace(/\s/g, '');
|
||||
const uniqueChars = [...new Set(normalizedInput.toUpperCase() + normalizedInput.toLowerCase())];
|
||||
|
||||
console.log(`Checking input: "${input}"\n${'='.repeat(50)}`);
|
||||
|
||||
// Check each character in input
|
||||
const availableChars = [...new Set(uniqueChars)]
|
||||
.filter(char => !usedFlags.has(char));
|
||||
|
||||
if (availableChars.length > 0) {
|
||||
console.log(`These characters of "${input}" are available to use for new annotations:`);
|
||||
availableChars.forEach(char => console.log(` '${char}' (${char.charCodeAt(0)})`));
|
||||
} else {
|
||||
const inputChars = new Set(normalizedInput.toLowerCase() + normalizedInput.toUpperCase());
|
||||
const renamable = Object.entries(allEntries)
|
||||
.filter(([flag, entry]) => entry.rename_ok && inputChars.has(flag))
|
||||
.sort((a, b) => a[0].localeCompare(b[0]));
|
||||
|
||||
if (renamable.length > 0) {
|
||||
console.log(`None of the characters of "${input}" are available to use for new annotations, but these ones are OK to be moved to make way for new annotations:`);
|
||||
renamable.forEach(([flag, entry]) => {
|
||||
console.log(` '${flag}': ${entry['#'] || 'No description'}${entry['//'] ? ` (${entry['//']})` : ''}`);
|
||||
});
|
||||
} else {
|
||||
console.log(`None of the characters of "${input}" are available to use for new annotations, and none of them are OK to be moved to make way for new annotations.`);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue