-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Retire sed #42
base: master
Are you sure you want to change the base?
Retire sed #42
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,73 +1,35 @@ | ||
#!/usr/bin/env bash | ||
set -e | ||
|
||
# we'll modify files in src/ and then revert our changes using | ||
# git checkout src/* so make sure they have no local changes | ||
if git status --porcelain | grep 'src/'; then | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved this up and restricted the check to only files in |
||
echo "Can't generate the docs when the git checkout isn't clean" | ||
exit 1 | ||
fi | ||
|
||
npm install --no-package-lock | ||
tsc -p tsconfig.docgen.json | ||
|
||
# https://github.com/TypeStrong/typedoc/issues/564 | ||
# i would like typedoc to group functions in categories but it's not supported | ||
# yet. So I hack it with their support for external modules... | ||
|
||
# we'll modify the files and then revert our changes using | ||
# git reset --HARD so make sure there are no local changes | ||
if [[ $(git status --porcelain) ]]; then | ||
echo "Can't generate the docs when the git checkout isn't clean" | ||
exit 1 | ||
fi | ||
|
||
# pre-process files | ||
node dist/scripts/make_doc_extra/make_doc_preprocess.js | ||
|
||
# trick for the 'Option' & 'Either' constants which typedoc skips as it clashes | ||
# with the 'Option' & 'Either' type synomym | ||
sed -i "s/const Option/const optionGlabiboulga/" src/Option.ts | ||
sed -i "s/const Either/const eitherGlabiboulga/" src/Either.ts | ||
sed -i "s/const LinkedList/const linkedListGlabiboulga/" src/LinkedList.ts | ||
sed -i "s/const Stream/const streamGlabiboulga/" src/Stream.ts | ||
sed -i "s/const Function0/const function0Glabiboulga/" src/Function.ts | ||
sed -i "s/const Function1/const function1Glabiboulga/" src/Function.ts | ||
sed -i "s/const Function2/const function2Glabiboulga/" src/Function.ts | ||
sed -i "s/const Function3/const function3Glabiboulga/" src/Function.ts | ||
sed -i "s/const Function4/const function4Glabiboulga/" src/Function.ts | ||
sed -i "s/const Function5/const function5Glabiboulga/" src/Function.ts | ||
sed -i "s/const Predicate/const predicateGlabiboulga/" src/Predicate.ts | ||
node dist/scripts/make_doc_extra/replace_in_ts.js | ||
|
||
# generate with typedoc | ||
./node_modules/typedoc/bin/typedoc --exclude "**/make_doc_extra/*.ts" --mode file --out apidoc --excludePrivate --excludeExternals --excludeNotExported --ignoreCompilerErrors --tsconfig tsconfig.prepublish.json src/index.ts | ||
|
||
# revert the 'Option' & 'Either' constant rename | ||
find apidoc -name "*.html" -exec sed -i 's/optionglabiboulga/Option/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/option<wbr>Glabiboulga/Option/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/eitherglabiboulga/Either/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/either<wbr>Glabiboulga/Either/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/linkedlistglabiboulga/LinkedList/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/linked<wbr>List<wbr>Glabiboulga/LinkedList/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/streamglabiboulga/Stream/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/stream<wbr>Glabiboulga/Stream/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function0glabiboulga/Function0/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function0<wbr>Glabiboulga/Function0/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function1glabiboulga/Function1/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function1<wbr>Glabiboulga/Function1/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function2glabiboulga/Function2/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function2<wbr>Glabiboulga/Function2/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function3glabiboulga/Function3/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function3<wbr>Glabiboulga/Function3/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function4glabiboulga/Function4/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function4<wbr>Glabiboulga/Function4/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function5glabiboulga/Function5/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/function5<wbr>Glabiboulga/Function5/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/predicateglabiboulga/Predicate/g' \{\} \; | ||
find apidoc -name "*.html" -exec sed -i 's/predicate<wbr>Glabiboulga/Predicate/g' \{\} \; | ||
|
||
# modify the output to say 'File' instead of 'Module' | ||
find apidoc -name "*.html" -exec sed -i 's/Module/File/g' \{\} \; | ||
node dist/scripts/make_doc_extra/replace_in_html.js | ||
|
||
# modify the paths to say 'files' instead of 'modules' | ||
mv apidoc/modules apidoc/files | ||
find apidoc -name "*.html" -exec sed -i 's/modules/files/g' \{\} \; | ||
|
||
node dist/scripts/make_doc_extra/make_doc_extra.js | ||
|
||
# we're happy with the output now, revert the changes I made | ||
# to the files to make typedoc think they're external modules | ||
git reset --hard HEAD | ||
git checkout src/* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import * as fs from 'fs'; | ||
import * as path from 'path'; | ||
import { FILE_REPLACEMENTS, replaceInFile, SimpleReplacement } from './replacements'; | ||
|
||
async function main() { | ||
const allHtmlReplacements = FILE_REPLACEMENTS | ||
.flatMap(([_, constReplacement]) => constReplacement.htmlReplacements) | ||
.appendAll([ | ||
new SimpleReplacement('Module', 'File'), | ||
new SimpleReplacement('modules', 'files'), | ||
]); | ||
|
||
const promises: Promise<void>[] = []; | ||
for await (const htmlFile of findHtml('apidoc')) { | ||
promises.push(replaceInFile(htmlFile, allHtmlReplacements)); | ||
} | ||
return Promise.all(promises); | ||
} | ||
|
||
async function* findHtml(dir: string): AsyncIterableIterator<string> { | ||
const children = await fs.promises.readdir(dir, {withFileTypes: true}); | ||
for (const child of children) { | ||
if (child.isDirectory()) { | ||
yield *findHtml(path.join(dir, child.name)) | ||
} else if (child.isFile() && child.name.endsWith('.html')) { | ||
yield path.join(dir, child.name); | ||
} | ||
} | ||
} | ||
|
||
main() | ||
.then() | ||
.catch(err => { | ||
console.error(err); | ||
process.exit(1); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import { replaceInFiles, FILE_REPLACEMENTS, SimpleReplacement } from './replacements'; | ||
import { Vector } from '../../src'; | ||
|
||
|
||
function main() { | ||
return FILE_REPLACEMENTS | ||
.map<[string, Vector<SimpleReplacement>]>( | ||
([file, replacement]) => [file, replacement.tsReplacements] | ||
) | ||
.transform(replaceInFiles); | ||
} | ||
|
||
main() | ||
.then() | ||
.catch(err => { | ||
console.error(err); | ||
process.exit(1); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
import * as fs from 'fs'; | ||
import * as readline from 'readline'; | ||
import { Vector } from '../../src'; | ||
import * as path from 'path'; | ||
|
||
export class SimpleReplacement { | ||
readonly src: RegExp; | ||
readonly trg: string; | ||
|
||
constructor(_src: string, _trg: string) { | ||
if (!_src.match(/^[a-zA-Z0-9<> ]+$/)) { | ||
throw new Error('Not safe for regex: ' + _src); | ||
} | ||
this.src = new RegExp(_src, 'g'); | ||
this.trg = _trg; | ||
} | ||
} | ||
|
||
const SUFFIX = 'Glabiboulga'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Btw, what's this? :) |
||
|
||
export class ConstReplacement { | ||
readonly tsReplacements: Vector<SimpleReplacement>; | ||
readonly htmlReplacements: Vector<SimpleReplacement>; | ||
|
||
constructor(constNames: string | Vector<string>) { | ||
const constNamesVector = constNames instanceof Vector ? constNames : Vector.of(constNames); | ||
this.tsReplacements = constNamesVector | ||
.map(constName => new SimpleReplacement( | ||
`const ${constName}`, | ||
`const ${constName}${SUFFIX}`, | ||
)); | ||
|
||
this.htmlReplacements = constNamesVector | ||
.flatMap(constName => Vector.of( | ||
new SimpleReplacement( | ||
`${constName}${SUFFIX}`.toLowerCase(), | ||
constName, | ||
), | ||
new SimpleReplacement( | ||
this.insertWbrBetweenParts(`${constName}${SUFFIX}`), | ||
constName, | ||
) | ||
)); | ||
} | ||
|
||
/** | ||
* CamelCase42Name -> Camel<wbr>Case42<wbr>Name | ||
*/ | ||
private insertWbrBetweenParts(text: string): string { | ||
if (!text.match(/^[A-Z]/)) { | ||
throw new Error('Must start with capital letter: ' + text); | ||
} | ||
|
||
const part = /[A-Z][^A-Z]*/g; | ||
function* parts(): IterableIterator<string> { | ||
for ( ; ; ) { | ||
const res = part.exec(text); | ||
if (!res) { | ||
return; | ||
} | ||
yield res[0]; | ||
} | ||
} | ||
return Vector.ofIterable(parts()).mkString('<wbr>'); | ||
} | ||
} | ||
|
||
export const FILE_REPLACEMENTS = Vector.of<[string, ConstReplacement]>( | ||
[path.join('src', 'Option.ts'), new ConstReplacement('Option')], | ||
[path.join('src', 'Either.ts'), new ConstReplacement('Either')], | ||
[path.join('src', 'LinkedList.ts'), new ConstReplacement('LinkedList')], | ||
[path.join('src', 'Stream.ts'), new ConstReplacement('Stream')], | ||
[path.join('src', 'Function.ts'), new ConstReplacement(Vector.of(0, 1, 2, 3, 4, 5).map(i => `Function${i}`))], | ||
[path.join('src', 'Predicate.ts'), new ConstReplacement('Predicate')], | ||
) | ||
|
||
export function replaceInFiles(fileReplacements: Vector<[string, Vector<SimpleReplacement>]>): Promise<void[]> { | ||
const promises = fileReplacements | ||
.map(([file, replacements]) => replaceInFile(file, replacements)); | ||
return Promise.all(promises); | ||
} | ||
|
||
export async function replaceInFile(file: string, replacements: Vector<SimpleReplacement>): Promise<void> { | ||
return new Promise<string>(async (resolve, reject) => { | ||
const inInterface = readline.createInterface({input: fs.createReadStream(file)}); | ||
try { | ||
const lines: string[] = []; | ||
for await (const line of inInterface) { | ||
lines.push( | ||
replacements | ||
.foldLeft(line, (l, repl) => l.replace(repl.src, repl.trg)) | ||
); | ||
} | ||
resolve(lines.map(l => l + '\n').join('')); | ||
} catch (err) { | ||
reject(err); | ||
} finally { | ||
inInterface.close(); | ||
} | ||
}).then(lines => fs.promises.writeFile(file, lines)); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"extends": "./tsconfig.base.json", | ||
"extends": "./tsconfig.json", | ||
"include": [ | ||
"src/**/*", | ||
"benchmarks/**/*" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"extends": "./tsconfig.base.json", | ||
"extends": "./tsconfig.json", | ||
"include": [ | ||
"src/**/*", | ||
"scripts/**/*" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,9 @@ | |
"outDir": "./dist", | ||
"declaration": true, | ||
"sourceMap": true, | ||
"lib": ["es2015", "dom"] // I need DOM because of typedoc.. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually |
||
} | ||
"lib": ["es2015", "dom", "esnext.asynciterable"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't check all files after previous contribution bringing this name, and that was a mistake. This time I found out that my IDE got lost and couldn't read any config, so it reported a lot of compilation errors. I don't know what's your favorite IDE but I suppose if you browse a lot you also gonna encounter something strange. I experimented with configs inheritance and found out that, in order to get maximum support from IDE (like code completion, jump to |
||
}, | ||
"include": [ | ||
"**/*" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
{ | ||
"extends": "./tsconfig.base.json", | ||
"extends": "./tsconfig.json", | ||
"include": [ | ||
"src/**/*", | ||
"tests/**/*" | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's to use async generators in scripts