closingbracket
v1.0.10
Published
Find in a string a closing bracket for an opening bracket. The search function will start from a specific start index in the string, identifies the start index of the next corresponding opening bracket and finds the corresponding closing bracket provided
Downloads
15
Readme
Closing Bracket Search
Find in a string a closing bracket for an opening bracket. The search function will start from a specific start index in the string, identifies the start index of the next corresponding opening bracket and finds the corresponding closing bracket provided as parameter. The search function return a object withe the start index, the index of opening bracket and the index of the closing bracket.
Example Closing Brackets
In general the syntactic structure of languages must respect the nested bracket structure. This means that opening a bracket with (
refers not to the next closing bracket found in the string. This can be visualized with an arithmetic expression (a-(b+c)+d)+e
. The opening bracket (
before the a
is not closed with the first closing bracket behind the c
. The corresponding bracket is closed behind variable d
. This library helps you in identification of the proper closing bracket for different brackets (),{},[],<>
.
Allowed Brackets
The bracket handler allows the following closing brackets:
)
with corresponding opening bracket(
}
with corresponding opening bracket{
]
with corresponding opening bracket[
<
with corresponding opening bracket>
Demo of BracketHandler
The library closingbracket.js
is imported in WebApp of type AppLSAC-1. Marco definitions in LaTeX have to match opening and closing brackets for parameter counts [3]
and parameters wrapped in brackets {}
. With the demo you can play around with bracket definitions in LaTeX.
- Demo BracketHandler` for LaTeX NewCommands
- This tool was created for the Wikiversity learning resource about LaTeX
With Browser
Use a script tag and import the library closingbracket.js
with:
<script src="js/closingbracket.js"></script>
The script tag assumes that the library was stored in the subdirectory js/
of your web project.
With NodeJS
npm install closingbracket --save
Use a script tag and import the library closingbracket.js
with:
const BracketHandler = require('closingbracket');
Use BracketHandler
With the import of the script/package you have a bracket handler BracketHandler
available that provides the functionality for handling corresponding opening and closing brackets.
var str = "MyCheck(char,(iasd+2),add(3,4),x); another_call(x,(y+20),(84*4))";
var vResult = BracketHandler.find_closing_bracket(str,")",2);
The function above start search for the closing bracket )
beginning from index 2 (i.e. the C
of MyCheck...
). It finds the corresponding opening bracket (
at position 7. and the closing bracket )
at position 32 (i.e. the )
after the add(3,4),x
). The function find_closing_bracket()
returns a JSON of the following structure:
vResult = {
"start_search": 2,
"openbracket_at": 7,
"closebracket_at": 32
};
BracketHandler for LaTeX
The BracketHandler is able to replace the definition of macros in LaTeX. As an example the \newcommand
definitions in LaTeX are used. In general LaTeX syntax is used for mathematical expressions in a thesis or for repeating text fragments with parameters.
Use-Case
Assume you want to use the following text fragments
- Title
hammer
: Thehammer
is used fornails
. - Title
bus
: Thebus
is used fortransportation
. - Title
car
: Thecar
is used fortransportation
. The text fragements differ just in a words and the tool (e.g.hammer
,car
, orbus
) is used multiple times. For this use case in general macros are defined.
\newcommand{\tool}[2]{Title #1: The #1 is used for #2}
The [2]
means, that the macro command \tool
has two parameters.
With that macro you can generate the text fragments above much easier by:
\tool{hammer}{nails}
\tool{hammer}{nails}
\tool{hammer}{nails}
The BracketHandler is able to expand the shorter definitions back to the longer definitions without macros.
For Wikiversity learning resources can handle mathematical expression. But for these mathematical expressions used macros might be expanded to the source latex code.
\int_{4}^{5} f(x) \, dx
\int_{a}^{b} f(y) \, dy
\int_{100}^{200} f(z) \, dz
The next line defines the corresponding command named \cmd
for the use generating an integral with 3 parameters.
\newcommand{\cmd}[3]{\int_{#1}^{#2} f(#3) \, d#3}
The source definition in LaTeX can be defined by the following command:
\cmd{4}{5}{x}
\cmd{a}{b}{y}
\cmd{100}{200}{z}
In Wikiversity the command \cmd
is unknown so the latex command must be expanded to the latex source definition of the command.
Replacement of Macro Definition
Now we assume the source text will look like this:
Text
\newcommand{\tool}[2]{Title #1: The #1 is used for #2}
\newcommand{\cmd}[3]{\int_{#1}^{#2} f(#3) d#3}
\tool{hammer}{nails}
\tool{car}{transportation}
\tool{cup}{drinking}
Mathematical expressions are
$\cmd{4}{5}{x}$ and $\cmd{a}{b}{y}$
The text above ist stored in the variable latex
in Javascript.
var latex="\\newcommand{\\tool}[2]{...";
// parse the newcommands in the string "latex"
var vNewCommands = BracketHandler.parse_newcommands(latex);
After parsing the newcommands in the text the variable vNewCommands
is a JSON with all the parse newcommand definition in the file. vNewCommands
will look like this for the example:
[
{
"name": "\\tool",
"definition": "Title #1: The #1 is used for #2",
"params": 2
},
{
"name": "\\cmd",
"definition": "\\int_{#1}^{#2} f(#3) d#3",
"params": 3
}
]
Now can use the newcommand definition for replacement in multiple files. You can even output vNewCommands
with the follwing javascript command formatted in the console.
console.log(JSON.stringify(vNewCommands,null,4));
Expand the Macros in the Source
Assume we the same source text above and the definition of new latex commands is stored in the same file with the text that applies the macros (this is not usually the case because for larger documents chapters and the newcommand definitions are stored in a separate file - e.g. the newcommands in file newcmds.tex
). Nevertheless parsing and replacing can be performed on the same file.
var latex="\\newcommand{\\tool}[2]{...";
// parse the newcommands in the string "latex"
var vNewCommands = BracketHandler.parse_newcommands(latex);
var result = BracketHandler.replace_newcommands(latex,vNewCommands);
console.log("Result: "+result);
Recursion Depth
Macros may also contain other LaTeX macros that are defined as newcommands. So replacement of the macro in first recursion may need further replacements of the replaced macros in the newcommand definition.
\newcommand{\tool}[2]{\tooltitle{#1} The #1 is used for #2}
\newcommand{\tooltitle}[1]{Title #1: }
\tool{hammer}{nails}
The first recursion will replace the macro \tool
to the following text:
\newcommand{\tool}[2]{\tooltitle{#1} The #1 is used for #2.}
\newcommand{\tooltitle}[1]{Title #1: }
\tooltitle{hammer} The hammer is used for nails.
The second recursion depth with replace the remaining commands (macro calls) for \tooltitle
to the following text:
\newcommand{\tool}[2]{\tooltitle{#1} The #1 is used for #2.}
\newcommand{\tooltitle}[1]{Title #1: }
Title hammer: The hammer is used for nails.
The replacement function replace_newcommands()
counts the number of recursions in which there is still a marco call found in the text. If the counted successful replacements are 0, then the replacement of newcommands terminates. Nevertheless maximal number of recursions are are set in the library (default is 5). If there function performs more than 5 recursions the replacement of newcommmands are terminated even there are some possible macro replacements remain in the text. The parameter
var latex="\\newcommand{\\tool}[2]{...";
// parse the newcommands in the string "latex"
var vNewCommands = BracketHandler.parse_newcommands(latex);
// maximal number of allowed recursion for replacement
var max_recursion = 10;
var result = BracketHandler.replace_newcommands(latex,vNewCommands,mmax_recursion);
console.log("Result: "+result);
The maximal number of allowed recursions is defined by
max_recursion
so that an infinite loop can be avoided. Infinite loops for the replacement occur, if there is a cycle newcommand replacment.
e.g. command \cmdA
uses \cmdB
in the definition and
\cmdB
uses \cmdA
again in its definition.
\newcommand{\cmdA}[1]{This macro A with parameter #1. Call macro B. \cmdB{#1}}
\newcommand{\cmdB}[1]{This is B for parameter #1. Call \cmdA{Nails} }
\cmdA{hammer}
The first recursion expands \cmdA{hammer}
to:
This macro A with parameter hammer.
Call marco B. \cmdB{hammer}}
The first replacement calls now macro B with the parameter hammer
, which expands to:
This macro A with parameter hammer. Call marco B.
This is B for parameter hammer. Call \cmdA{NAILS}
Now command A in called again with a different parameter NAILS
. This expands to:
This macro A with parameter hammer. Call marco B.
This is B for parameter hammer. Call
This macro A with parameter NAILS.
Call marco B. \cmdB{NAILS}}
The cyclic replacement would not terminate if max_recursion
would not be set for preventing the function from getting into an infinite loop.
Source and Destination of LaTeX Source - Browser
You can create a simple AppLSAC with two text areas
- one for the source and
- one for the results of the replacement.
Create a JSON File for Parsed newcommands
in NodeJS
To create the file newcommands.json
for JSON with parsed newcommands use the following example.
var fs = require("fs");
fs.readFile("newcmds.tex", function(err, buf) {
let latex = buf.toString()
console.log("Source: "+latex);
// parse newcommands
var vNewCommands = BracketHandler.parse_newcommands(latex);
let data = JSON.stringify(vNewCommands,null,4);
fs.writeFile("newcommands.json", data, (err) => {
if (err) console.log(err);
console.log("vNewCommands saved to newcommands.json.");
});
});
Requiring Macro Definitions in NodeJS
If you stored the macros in a file newcommands.json
you can require the JSON and used the newcommands multiple times without the need to parse a source file with newcommand definitions again. This is helpful e.g. for a master thesis where the newcommands are defined in a separate file (e.g. newcmds.tex
) and the chapters are stored in different files too. So reading the newcommands from a JSON can be performed like this:
let vNewCommands = require('./newcommands.json');
Wikiversity
This piece of software was created on GitLab as support material for the learning resource about privacy-friendly webbased applications AppLSAC
](https://en.wikiversity.org/wiki/AppLSAC) on Wikiversity. An AppLSAC
run completely in the browser without the need to submit any user generated data to a server. This package LoadFile4DOM
is designed to learn about the first step:
- (Load) Load File into a browser for processing with an HTML5-WebApp (AppLSAC-1 or AppLSAC-2). The library
LoadFile4DOM
serves to cover the loading feature. - (Process) Processing data can be done with any Javascript-libraries of your choice that can perform its task without submission of user generated data to a remote server.
HandleBars4Code
processes a JSON as input (UML for Javascript) to generate the JavaScript library or theREADME.md
documentation for a package. - (Save) If users want to save the processed results, it is recommended to look at the FileSaver.js library provided by Eli Grey.
For Developers
If want to expand the functionality of this library for your purposes
- fork the library on GitHub,
- add more functionality to the file
src/closingbracket.js
. - run
npm run build
, which updates thesrc/main.js
dist/closingbracket.js
. - at the very end of the file an associative array is defined that aggregates all the function that you want to export in NodeJS.