diff --git a/README.md b/README.md index 1544da3..dfe6e11 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,7 @@ VHDL formatter web online written in javascript - use local storage to store settings - add `main.js` +- treat key words and type names separately ### 2.3 [2018-02-22] diff --git a/VHDLFormatter.js b/VHDLFormatter.js index 32236c9..fde25c5 100644 --- a/VHDLFormatter.js +++ b/VHDLFormatter.js @@ -118,23 +118,19 @@ function ReplaceKeyWords(text, keywords) { } return text; } -function SetKeywordCase(input, keywordcase, keywords, typenames) { +function SetKeywordCase(input, keywordcase, keywords) { let inputcase = keywordcase.toLowerCase(); - switch (keywordcase.toLowerCase()) { + switch (inputcase) { case "lowercase": ToLowerCases(keywords); - ToLowerCases(typenames); break; case "defaultcase": ToCamelCases(keywords); - ToCamelCases(typenames); break; case "uppercase": ToUpperCases(keywords); - ToUpperCases(typenames); } input = ReplaceKeyWords(input, keywords); - input = ReplaceKeyWords(input, typenames); return input; } function SetNewLinesAfterSymbols(text, newLineSettings) { @@ -160,13 +156,14 @@ function SetNewLinesAfterSymbols(text, newLineSettings) { } exports.SetNewLinesAfterSymbols = SetNewLinesAfterSymbols; class BeautifierSettings { - constructor(removeComments, removeReport, checkAlias, signAlign, signAlignAll, keywordCase, indentation, newLineSettings, endOfLine) { + constructor(removeComments, removeReport, checkAlias, signAlign, signAlignAll, keywordCase, typeNameCase, indentation, newLineSettings, endOfLine) { this.RemoveComments = removeComments; this.RemoveAsserts = removeReport; this.CheckAlias = checkAlias; this.SignAlignRegional = signAlign; this.SignAlignAll = signAlignAll; this.KeywordCase = keywordCase; + this.TypeNameCase = typeNameCase; this.Indentation = indentation; this.NewLineSettings = newLineSettings; this.EndOfLine = endOfLine; @@ -190,7 +187,8 @@ function beautify(input, settings) { input = input.replace(/@@comments[0-9]+/g, ''); comments = []; } - input = SetKeywordCase(input, "uppercase", KeyWords, TypeNames); + input = SetKeywordCase(input, "uppercase", KeyWords); + input = SetKeywordCase(input, "uppercase", TypeNames); input = RemoveExtraNewLines(input); input = input.replace(/[\t ]+/g, ' '); input = input.replace(/\([\t ]+/g, '\('); @@ -204,10 +202,13 @@ function beautify(input, settings) { input = arr.join("\r\n"); input = input.replace(/(PORT|GENERIC)\s+MAP/g, '$1 MAP'); input = input.replace(/(PORT|PROCESS|GENERIC)[\s]*\(/g, '$1 ('); - input = SetNewLinesAfterSymbols(input, settings.NewLineSettings); - arr = input.split("\r\n"); - ApplyNoNewLineAfter(arr, settings.NewLineSettings.noNewLineAfter); - input = arr.join("\r\n"); + let newLineSettings = settings.NewLineSettings; + if (newLineSettings != null) { + input = SetNewLinesAfterSymbols(input, newLineSettings); + arr = input.split("\r\n"); + ApplyNoNewLineAfter(arr, newLineSettings.noNewLineAfter); + input = arr.join("\r\n"); + } input = input.replace(/([a-zA-Z0-9\); ])\);(@@comments[0-9]+)?@@end/g, '$1\r\n);$2@@end'); input = input.replace(/[ ]?([&=:\-<>\+|\*])[ ]?/g, ' $1 '); input = input.replace(/(\d+e) +([+\-]) +(\d+)/g, '$1$2$3'); // fix exponential notation format broken by previous step @@ -237,7 +238,8 @@ function beautify(input, settings) { } arr = FormattedLineToString(result, settings.Indentation); input = arr.join("\r\n"); - input = SetKeywordCase(input, settings.KeywordCase, KeyWords, TypeNames); + input = SetKeywordCase(input, settings.KeywordCase, KeyWords); + input = SetKeywordCase(input, settings.TypeNameCase, TypeNames); input = replaceEscapedWords(input, quotes, ILQuote); input = replaceEscapedWords(input, singleQuotes, ILSingleQuote); input = replaceEscapedComments(input, comments, ILCommentPrefix); @@ -253,7 +255,7 @@ exports.beautify = beautify; function replaceEscapedWords(input, arr, prefix) { for (var i = 0; i < arr.length; i++) { var text = arr[i]; - var regex = new RegExp(prefix + "{" + text.length + "}"); + var regex = new RegExp("(" + prefix + "){" + text.length + "}"); input = input.replace(regex, text); } return input; @@ -281,6 +283,9 @@ function FormattedLineToString(arr, indentation) { if (arr == null) { return result; } + if (indentation == null) { + indentation = ""; + } arr.forEach(i => { if (i instanceof FormattedLine) { if (i.Line.length > 0) { diff --git a/VHDLFormatter.ts b/VHDLFormatter.ts index a7e8d6c..0b6ad4a 100644 --- a/VHDLFormatter.ts +++ b/VHDLFormatter.ts @@ -152,24 +152,20 @@ function ReplaceKeyWords(text: string, keywords: Array): string { return text; } -function SetKeywordCase(input: string, keywordcase: string, keywords: string[], typenames: string[]): string { +function SetKeywordCase(input: string, keywordcase: string, keywords: string[]): string { let inputcase: string = keywordcase.toLowerCase(); - switch (keywordcase.toLowerCase()) { + switch (inputcase) { case "lowercase": ToLowerCases(keywords); - ToLowerCases(typenames); break; case "defaultcase": ToCamelCases(keywords); - ToCamelCases(typenames); break; case "uppercase": ToUpperCases(keywords); - ToUpperCases(typenames); } input = ReplaceKeyWords(input, keywords); - input = ReplaceKeyWords(input, typenames); return input; } @@ -203,11 +199,12 @@ export class BeautifierSettings { SignAlignAll: boolean; SignAlignKeyWords: Array; KeywordCase: string; + TypeNameCase: string; Indentation: string; NewLineSettings: NewLineSettings; EndOfLine: string; constructor(removeComments: boolean, removeReport: boolean, checkAlias: boolean, - signAlign: boolean, signAlignAll: boolean, keywordCase: string, indentation: string, + signAlign: boolean, signAlignAll: boolean, keywordCase: string, typeNameCase: string, indentation: string, newLineSettings: NewLineSettings, endOfLine: string) { this.RemoveComments = removeComments; this.RemoveAsserts = removeReport; @@ -215,6 +212,7 @@ export class BeautifierSettings { this.SignAlignRegional = signAlign; this.SignAlignAll = signAlignAll; this.KeywordCase = keywordCase; + this.TypeNameCase = typeNameCase; this.Indentation = indentation; this.NewLineSettings = newLineSettings; this.EndOfLine = endOfLine; @@ -241,7 +239,8 @@ export function beautify(input: string, settings: BeautifierSettings) { comments = []; } - input = SetKeywordCase(input, "uppercase", KeyWords, TypeNames); + input = SetKeywordCase(input, "uppercase", KeyWords); + input = SetKeywordCase(input, "uppercase", TypeNames); input = RemoveExtraNewLines(input); input = input.replace(/[\t ]+/g, ' '); input = input.replace(/\([\t ]+/g, '\('); @@ -256,11 +255,13 @@ export function beautify(input: string, settings: BeautifierSettings) { input = arr.join("\r\n"); input = input.replace(/(PORT|GENERIC)\s+MAP/g, '$1 MAP'); input = input.replace(/(PORT|PROCESS|GENERIC)[\s]*\(/g, '$1 ('); - input = SetNewLinesAfterSymbols(input, settings.NewLineSettings); - - arr = input.split("\r\n"); - ApplyNoNewLineAfter(arr, settings.NewLineSettings.noNewLineAfter); - input = arr.join("\r\n"); + let newLineSettings = settings.NewLineSettings; + if (newLineSettings != null) { + input = SetNewLinesAfterSymbols(input, newLineSettings); + arr = input.split("\r\n"); + ApplyNoNewLineAfter(arr, newLineSettings.noNewLineAfter); + input = arr.join("\r\n"); + } input = input.replace(/([a-zA-Z0-9\); ])\);(@@comments[0-9]+)?@@end/g, '$1\r\n);$2@@end'); input = input.replace(/[ ]?([&=:\-<>\+|\*])[ ]?/g, ' $1 '); @@ -292,13 +293,13 @@ export function beautify(input: string, settings: BeautifierSettings) { arr = FormattedLineToString(result, settings.Indentation); input = arr.join("\r\n"); - input = SetKeywordCase(input, settings.KeywordCase, KeyWords, TypeNames); + input = SetKeywordCase(input, settings.KeywordCase, KeyWords); + input = SetKeywordCase(input, settings.TypeNameCase, TypeNames); input = replaceEscapedWords(input, quotes, ILQuote); input = replaceEscapedWords(input, singleQuotes, ILSingleQuote); input = replaceEscapedComments(input, comments, ILCommentPrefix); input = replaceEscapedWords(input, backslashes, ILBackslash); - input = input.replace(new RegExp(ILSemicolon, "g"), ";"); input = input.replace(/@@[a-z]+/g, ""); var escapedTexts = new RegExp("[" + ILBackslash + ILQuote + ILSingleQuote + "]", "g"); @@ -310,7 +311,7 @@ export function beautify(input: string, settings: BeautifierSettings) { function replaceEscapedWords(input: string, arr: Array, prefix: string): string { for (var i = 0; i < arr.length; i++) { var text = arr[i]; - var regex = new RegExp(prefix + "{" + text.length + "}"); + var regex = new RegExp("(" + prefix + "){" + text.length + "}"); input = input.replace(regex, text); } return input; @@ -343,6 +344,9 @@ export function FormattedLineToString(arr: (FormattedLine | FormattedLine[])[], if (arr == null) { return result; } + if (indentation == null) { + indentation = ""; + } arr.forEach(i => { if (i instanceof FormattedLine) { if (i.Line.length > 0) { diff --git a/index.html b/index.html index 15881df..91bb53b 100644 --- a/index.html +++ b/index.html @@ -1,6 +1,7 @@ + VHDL Beautifier, Formatter Online @@ -240,13 +247,27 @@ -
Keyword Case: + Keyword case: | | +
+ e.g. begin, case, when +
+
+
Type name case: + | + | + +
+ e.g. boolean, natural, string +
New line after @@ -459,6 +480,7 @@ document.getElementById("use_space").checked = indentation != "\t"; document.getElementById("customise_indentation").value = indentation; document.getElementById("keyword").elements.namedItem("keywordcase").value = beautifierSettings.KeywordCase; + document.getElementById("typename").elements.namedItem("typenamecase").value = beautifierSettings.TypeNameCase; document.getElementById("mix_letter").checked = setting.mixLetter; var eof = beautifierSettings.EndOfLine eof = eof.replace(/\r/g, "\\r"); @@ -514,6 +536,7 @@ var compress = document.getElementById("compress").checked; var cust_indent = document.getElementById("customise_indentation").value; var keywordcase = document.getElementById("keyword").elements.namedItem("keywordcase").value; + var typenamecase = document.getElementById("typename").elements.namedItem("typenamecase").value; var mix_letter = document.getElementById("mix_letter").checked; var endOfLine = document.getElementById("cust_eol").value; endOfLine = endOfLine.replace(/\\r/g, "\r"); @@ -556,6 +579,7 @@ beautifierSettings = new BeautifierSettings(remove_comments, remove_report, check_alias, sign_align, sign_align_all, keywordcase, + typenamecase, indentation, newLineSettings, endOfLine); diff --git a/tests/VHDLFormatterUnitTests.ts b/tests/VHDLFormatterUnitTests.ts index bf94c06..a0042d2 100644 --- a/tests/VHDLFormatterUnitTests.ts +++ b/tests/VHDLFormatterUnitTests.ts @@ -917,6 +917,8 @@ function IntegrationTest() { IntegrationTest76(); IntegrationTest77(); IntegrationTest78(); + IntegrationTest79(); + IntegrationTest80(); } function IntegrationTest23() { @@ -1078,6 +1080,7 @@ function IntegrationTest44() { function IntegrationTest45() { let settings = GetDefaultSettings(); settings.KeywordCase = "lowercase"; + settings.TypeNameCase = "lowercase"; settings.Indentation = " "; let input = 'REPORT\n"A_ARITH_MOD_tester.main Tester is now ready. A total OF " &\nINTEGER\'image(totalTests) & " tests have been detected.";'; let expected = 'report\r\n "A_ARITH_MOD_tester.main Tester is now ready. A total OF " &\r\n integer\'image(totalTests) & " tests have been detected.";'; @@ -1088,6 +1091,7 @@ function IntegrationTest45() { function IntegrationTest46() { let settings = GetDefaultSettings(); settings.KeywordCase = "lowercase"; + settings.TypeNameCase = "lowercase"; let input = 'impure function delay(\r\n l : integer\r\n) return time is\r\n variable r : real;\r\nbegin\r\n result := 2ps;\r\n return result;\r\nend function;'; let actual = beautify(input, settings); assertAndCountTest("impure function indent", input, actual); @@ -1096,6 +1100,7 @@ function IntegrationTest46() { function IntegrationTest47() { let settings = GetDefaultSettings(); settings.KeywordCase = "lowercase"; + settings.TypeNameCase = "lowercase"; settings.Indentation = " "; let input = 'result := 1\r\n 1\r\n + 1; -- hello'; let actual = beautify(input, settings); @@ -1105,6 +1110,7 @@ function IntegrationTest47() { function IntegrationTest48() { let settings = GetDefaultSettings(); settings.KeywordCase = "lowercase"; + settings.TypeNameCase = "lowercase"; let input = 'function delay(\r\n l : integer\r\n) return time is\r\n variable r : real;\r\nbegin\r\n result := 2ps;\r\n return result;\r\nend function;'; let actual = beautify(input, settings); assertAndCountTest("function indent", input, actual); @@ -1139,6 +1145,7 @@ function IntegrationTest51() { function IntegrationTest52() { let settings = GetDefaultSettings(); settings.KeywordCase = "lowercase"; + settings.TypeNameCase = "lowercase"; let input = 'function a(\r\n b : integer\r\n c : integer\r\n) return integer;\r\n\r\nimpure function a(\r\n b : integer\r\n c : integer\r\n) return integer;\r\n\r\nfunction a(\r\n b : integer\r\n c : integer\r\n) return integer;'; let actual = beautify(input, settings); assertAndCountTest("function without sequential statements", input, actual); @@ -1147,6 +1154,7 @@ function IntegrationTest52() { function IntegrationTest53() { let settings = GetDefaultSettings(); settings.KeywordCase = "lowercase"; + settings.TypeNameCase = "lowercase"; let input = 'function a(\r\n b : integer\r\n c : integer\r\n) return integer;\r\n\r\nimpure function a(\r\n b : integer\r\n c : integer\r\n) return integer;\r\n\r\nfunction a(\r\n b : integer\r\n c : integer\r\n) return integer;'; let actual = beautify(input, settings); assertAndCountTest("function without sequential statements, without new line", input, actual); @@ -1185,6 +1193,7 @@ function IntegrationTest57() { function IntegrationTest58() { let settings = GetDefaultSettings(); settings.KeywordCase = "lowercase"; + settings.TypeNameCase = "lowercase"; let input = 'package body a is\r\n procedure b(\r\n signal a : in boolean;\r\n b : boolean\r\n ) is\r\n begin\r\n a = 1\r\n end procedure b;\r\nend a;'; let actual = beautify(input, settings); assertAndCountTest("package body", input, actual); @@ -1193,6 +1202,7 @@ function IntegrationTest58() { function IntegrationTest59() { let settings = GetDefaultSettings(); settings.KeywordCase = "lowercase"; + settings.TypeNameCase = "lowercase"; let input = 'package body a is\r\n procedure b(\r\n signal a : in boolean;\r\n b : boolean) is\r\n begin\r\n a = 1\r\n end procedure b;\r\nend a;'; let actual = beautify(input, settings); assertAndCountTest("package body 2", input, actual); @@ -1343,19 +1353,32 @@ function IntegrationTest76() { function IntegrationTest77() { let settings = GetDefaultSettings(); - settings.SignAlignAll = true; let input = "WHEN -2;\r\nSIGNAL +0;"; let actual = beautify(input, settings); - assertAndCountTest("negative sign and number", input, actual); + assertAndCountTest("negative sign and number after key word", input, actual); } function IntegrationTest78() { let settings = GetDefaultSettings(); - settings.SignAlignAll = true; let input = "sfixed(4 downto - 18);\r\nx <= to_sfixed( - 2.3, x);\r\nresize(x + 1, 4, - 18) when others;"; let expected = "sfixed(4 DOWNTO -18);\r\nx <= to_sfixed(-2.3, x);\r\nresize(x + 1, 4, -18) WHEN OTHERS;"; let actual = beautify(input, settings); - assertAndCountTest("negative sign and number", expected, actual); + assertAndCountTest("negative sign and number after symbol", expected, actual); +} + +function IntegrationTest79() { + let settings = new BeautifierSettings(false, false, false, false, false, "lowercase", "uppercase", null, null, "\r\n"); + settings.SignAlignAll = true; + let input = "case when others;\r\nx : STRING;\r\ny : BIT;"; + let actual = beautify(input, settings); + assertAndCountTest("uppercase typename and lowercase keyword", input, actual); +} + +function IntegrationTest80() { + let settings = GetDefaultSettings(); + let input = 'FUNCTION "abs" (arg : sfixed) RETURN sfixed;'; + let actual = beautify(input, settings); + assertAndCountTest("function name in quotes", input, actual); } function GetDefaultSettings(indentation: string = " "): BeautifierSettings { @@ -1367,7 +1390,7 @@ function GetDefaultSettings(indentation: string = " "): BeautifierSettings { } function getDefaultBeautifierSettings(newLineSettings: NewLineSettings, indentation: string = " "): BeautifierSettings { - return new BeautifierSettings(false, false, false, false, false, "uppercase", indentation, newLineSettings, "\r\n"); + return new BeautifierSettings(false, false, false, false, false, "uppercase", "uppercase", indentation, newLineSettings, "\r\n"); } function IntegrationTest20() {