From 6d0656a53a784a2517a66b60efec83a88a3fb8d7 Mon Sep 17 00:00:00 2001 From: Kishikawa Katsumi Date: Tue, 18 Mar 2025 23:21:10 +0900 Subject: [PATCH] Remove RegexBuilder (DSL) exec tester feature --- Package.swift | 12 - Public/css/common.css | 19 +- Public/index.html | 285 +++++++++------------- Public/js/app.js | 98 +------- Public/js/views/match_info_view.js | 70 ------ Public/js/views/test_editor.js | 7 +- Sources/App/Models/ExecRequest.swift | 1 - Sources/App/routes.swift | 25 -- Sources/BuilderTester/Main.swift | 140 ----------- Tests/RegexTests/BuilderTesterTests.swift | 53 ---- 10 files changed, 114 insertions(+), 596 deletions(-) delete mode 100644 Public/js/views/match_info_view.js delete mode 100644 Sources/BuilderTester/Main.swift delete mode 100644 Tests/RegexTests/BuilderTesterTests.swift diff --git a/Package.swift b/Package.swift index 287bba9..20a731c 100644 --- a/Package.swift +++ b/Package.swift @@ -12,17 +12,6 @@ let package = Package( .package(url: "https://github.com/vapor/leaf.git", from: "4.4.1"), ], targets: [ - .executableTarget( - name: "BuilderTester", - dependencies: [ - .product(name: "_StringProcessing", package: "swift-experimental-string-processing"), - .product(name: "_RegexParser", package: "swift-experimental-string-processing"), - ], - swiftSettings: [ - .unsafeFlags(["-Xfrontend", "-disable-availability-checking"]), - .unsafeFlags(["-cross-module-optimization"], .when(configuration: .release)) - ] - ), .executableTarget( name: "DSLConverter", dependencies: [ @@ -79,7 +68,6 @@ let package = Package( ), .testTarget( name: "RegexTests", dependencies: [ - .target(name: "BuilderTester"), .target(name: "DSLConverter"), .target(name: "DSLParser"), .target(name: "ExpressionParser"), diff --git a/Public/css/common.css b/Public/css/common.css index bf05cfd..a36b55c 100644 --- a/Public/css/common.css +++ b/Public/css/common.css @@ -3,13 +3,6 @@ min-width: 180px; } -.builder-tab-pane.test-editor-container { - max-height: 40vh; -} -#match-info-container { - max-height: 40vh; -} - .active-tick .checkable::after { font-family: "Font Awesome 6 Pro"; content: "\f00c"; @@ -69,18 +62,8 @@ box-shadow: none; } -#builder-exec-spinner { - color: #adb5bd; -} - -#run-button { - border: solid 2px #0d6efd; - border-radius: 11px; - font-size: 90%; -} - @media (min-width: 576px) { - .tab-content { + .root-container { height: 100%; } } diff --git a/Public/index.html b/Public/index.html index b5eb12d..a196bf2 100644 --- a/Public/index.html +++ b/Public/index.html @@ -39,187 +39,124 @@

- - -
-
-
-
-
-
Regular Expression
- -
-
-
Test String
+
+
+
+
+
Regular Expression
+ - -
-
-
-
-
-
- Builder DSL - - - - - - +
+
+ no match
-
-
-
-
-
-
-
Test String
-
-
-
- no match -
-
-
-
-
-
-
Match Information
-
-
-
-
+
+
+
+
+
+
Builder DSL
+
+
@@ -259,4 +196,4 @@

- \ No newline at end of file + diff --git a/Public/js/app.js b/Public/js/app.js index 1e58964..42eb67b 100644 --- a/Public/js/app.js +++ b/Public/js/app.js @@ -6,7 +6,6 @@ import { TestEditor } from "./views/test_editor"; import { DSLView } from "./views/dsl_view"; import { DSLEditor } from "./views/dsl_editor"; -import { MatchInfoView } from "./views/match_info_view"; import { DSLHighlighter } from "./views/dsl_highlighter"; @@ -37,7 +36,7 @@ export class App { ); this.patternTestEditor = new TestEditor( - document.querySelector(".pattern-tab-pane.test-editor-container") + document.querySelector(".test-editor-container") ); this.patternTestEditor.addEventListener("change", () => this.onPatternTestEditorChange() @@ -45,42 +44,6 @@ export class App { this.dslView = new DSLView(document.getElementById("dsl-view-container")); - const tabEl = document.getElementById("builder-tab"); - tabEl.addEventListener("shown.bs.tab", (event) => { - if (!this.dslEditor) { - this.dslEditor = new DSLEditor( - document.getElementById("dsl-editor-container") - ); - this.dslEditor.addEventListener("change", () => - this.onDSLEditorChange() - ); - this.dslEditor.value = this.stateProxy.builder; - - this.runButton = document.getElementById("run-button"); - this.runButton.addEventListener("click", () => { - this.onDSLEditorRunClick(); - }); - } - - if (!this.builderTestEditor) { - this.builderTestEditor = new TestEditor( - document.querySelector(".builder-tab-pane.test-editor-container") - ); - this.builderTestEditor.addEventListener("change", () => - this.onBuilderTestEditorChange() - ); - this.builderTestEditor.value = this.stateProxy.text2; - } - - if (!this.matchInfoView) { - this.matchInfoView = new MatchInfoView( - document.getElementById("match-info-container") - ); - } - - this.onDSLEditorChange(); - }); - this.runner = new Runner(); this.runner.onready = this.onRunnerReady.bind(this); this.runner.onresponse = this.onRunnerResponse.bind(this); @@ -326,63 +289,6 @@ export class App { this.encodeState(); } - onDSLEditorRunClick() { - document.getElementById("run-button-icon").classList.add("d-none"); - document.getElementById("run-button-spinner").classList.remove("d-none"); - - const method = "POST"; - const params = { - method: "testBuilder", - pattern: this.dslEditor.value, - text: this.builderTestEditor.value, - matchOptions: this.matchOptions.value, - }; - const body = JSON.stringify(params); - const headers = { - Accept: "application/json", - "Content-Type": "application/json", - }; - fetch("/api/rest/testBuilder", { method, headers, body }) - .then((response) => { - return response.json(); - }) - .then((response) => { - const result = response.result; - if (result && result.trim()) { - const matches = JSON.parse(response.result); - this.builderTestEditor.matches = matches; - this.matchInfoView.matches = matches; - this.updateMatchCount(matches.length, "dsl-match-count"); - } else { - this.builderTestEditor.matches = []; - this.matchInfoView.matches = []; - this.updateMatchCount(0, "dsl-match-count"); - } - const error = response.error; - if (error && error.trim()) { - this.dslEditor.error = error; - } else { - this.dslEditor.error = ""; - } - }) - .catch((error) => {}) - .finally(() => { - document.getElementById("run-button-icon").classList.remove("d-none"); - document.getElementById("run-button-spinner").classList.add("d-none"); - }); - } - - onBuilderTestEditorChange() { - this.runner.run({ - method: "testBuilder", - pattern: this.dslEditor.value, - text: this.builderTestEditor.value, - matchOptions: this.matchOptions.value, - }); - - this.encodeState(); - } - onRunnerReady() { const value = this.expressionField.value; if (value) { @@ -427,8 +333,6 @@ export class App { } this.dslView.error = response.error; break; - case "testBuilder": - break; } } } diff --git a/Public/js/views/match_info_view.js b/Public/js/views/match_info_view.js deleted file mode 100644 index a784602..0000000 --- a/Public/js/views/match_info_view.js +++ /dev/null @@ -1,70 +0,0 @@ -"use strict"; - -import { EventDispatcher } from "@createjs/easeljs"; - -export class MatchInfoView extends EventDispatcher { - constructor(container) { - super(); - this.container = container; - this.init(container); - } - - set matches(matches) { - this.container.innerHTML = ""; - - for (const match of matches) { - const table = document.createElement("table"); - this.container.appendChild(table); - table.classList.add( - "table", - "table-sm", - "table-borderless", - "table-striped", - "my-1" - ); - const tbody = document.createElement("tbody"); - table.appendChild(tbody); - const tr = document.createElement("tr"); - tbody.appendChild(tr); - const td1 = document.createElement("td"); - tr.appendChild(td1); - td1.textContent = "Match"; - const td2 = document.createElement("td"); - tr.appendChild(td2); - td2.textContent = match.value; - const td3 = document.createElement("td"); - tr.appendChild(td3); - td3.textContent = `${match.location.start}-${match.location.end}`; - const td4 = document.createElement("td"); - tr.appendChild(td4); - td4.textContent = ""; - - for (const [i, capture] of match.captures.entries()) { - const table = document.createElement("table"); - table.classList.add( - "table", - "table-sm", - "table-borderless", - "table-striped", - "my-1" - ); - const tr = document.createElement("tr"); - tbody.appendChild(tr); - const td1 = document.createElement("td"); - tr.appendChild(td1); - td1.textContent = `Group #${i + 1}`; - const td2 = document.createElement("td"); - tr.appendChild(td2); - td2.textContent = capture.value; - const td3 = document.createElement("td"); - tr.appendChild(td3); - td3.textContent = `${capture.location.start}-${capture.location.end}`; - const td4 = document.createElement("td"); - tr.appendChild(td4); - td4.innerHTML = `${capture.type}`; - } - } - } - - init(container) {} -} diff --git a/Public/js/views/test_editor.js b/Public/js/views/test_editor.js index 1607a66..4299cdc 100644 --- a/Public/js/views/test_editor.js +++ b/Public/js/views/test_editor.js @@ -60,12 +60,7 @@ export class TestEditor extends EventDispatcher { set matches(matches) { this.highlighter.draw(matches); - tippy(".pattern-tab-pane.test-editor-container span[data-tippy-content]", { - allowHTML: true, - animation: false, - placement: "bottom", - }); - tippy(".builder-tab-pane.test-editor-container span[data-tippy-content]", { + tippy(".test-editor-container span[data-tippy-content]", { allowHTML: true, animation: false, placement: "bottom", diff --git a/Sources/App/Models/ExecRequest.swift b/Sources/App/Models/ExecRequest.swift index f95470d..54453f7 100644 --- a/Sources/App/Models/ExecRequest.swift +++ b/Sources/App/Models/ExecRequest.swift @@ -13,5 +13,4 @@ enum RequestMethod: String, Codable { case convertToPattern case match case parseDSL - case testBuilder } diff --git a/Sources/App/routes.swift b/Sources/App/routes.swift index fb8563f..c94ab09 100644 --- a/Sources/App/routes.swift +++ b/Sources/App/routes.swift @@ -49,14 +49,6 @@ func routes(_ app: Application) throws { let pattern = request.pattern let response = try parseDSL(pattern: pattern) - if let message = String(data: try encoder.encode(response), encoding: .utf8) { - ws.send(message) - } - case .testBuilder: - let builder = request.pattern - let text = request.text - let response = try testBuilder(builder, text: text) - if let message = String(data: try encoder.encode(response), encoding: .utf8) { ws.send(message) } @@ -115,18 +107,6 @@ func routes(_ app: Application) throws { return response } - app.on(.POST, "api", "rest", "testBuilder", body: .collect(maxSize: "1mb")) { (req) -> ResultResponse in - guard let request = try? req.content.decode(ExecRequest.self) else { - throw Abort(.badRequest) - } - - let builder = request.pattern - let text = request.text - let response = try testBuilder(builder, text: text) - - return response - } - func parseExpression(pattern: String, matchOptions: [String]) throws -> ResultResponse { let (stdout, stderr) = try exec(command: "ExpressionParser", arguments: pattern, matchOptions.joined(separator: ",")) return ResultResponse(method: .parseExpression, result: stdout, error: stderr) @@ -147,11 +127,6 @@ func routes(_ app: Application) throws { return ResultResponse(method: .parseDSL, result: stdout, error: stderr) } - func testBuilder(_ builder: String, text: String) throws -> ResultResponse { - let (stdout, stderr) = try exec(command: "BuilderTester", arguments: builder, text) - return ResultResponse(method: .testBuilder, result: stdout, error: stderr) - } - func exec(command: String, arguments: String...) throws -> (stdout: String, stderr: String) { let process = Process() let executableURL = URL( diff --git a/Sources/BuilderTester/Main.swift b/Sources/BuilderTester/Main.swift deleted file mode 100644 index ddb15ac..0000000 --- a/Sources/BuilderTester/Main.swift +++ /dev/null @@ -1,140 +0,0 @@ -import Foundation - -@main -struct Main { - static func main() throws { - do { - let builder = CommandLine.arguments[1] - let text = CommandLine.arguments[2] - - let regexVarName = "regex_\(UUID().uuidString.replacingOccurrences(of: "-", with: ""))" - var code = "" - code = "let \(regexVarName) = \(builder)" - - let script = #""" - import Foundation - import RegexBuilder - import _StringProcessing - - struct Match: Codable { - let location: Location - let value: String - let captures: [Group] - } - - struct Group: Codable { - let location: Location? - let value: String? - let type: String - } - - struct Location: Codable { - let start: Int - let end: Int - } - - \#(code) - - let text = """ - \#(text) - """ - - let matches = text.matches(of: \#(regexVarName)) - - let results: [Match] = matches.map { - let types = Mirror(reflecting: $0.output).children.map { type(of: $0.value) } - var captures = [Group]() - let outputs = Mirror(reflecting: $0).children.filter { $0.label == "anyRegexOutput" }.map { $0.value } - for output in outputs { - let elements = Mirror(reflecting: output).children.filter { $0.label == "_elements" }.map { $0.value } - for element in elements { - let reps = Mirror(reflecting: element).children.map { $0.value } - for rep in reps { - let contents = Mirror(reflecting: rep).children.filter { $0.label == "content" }.map { $0.value } - for content in contents { - let optionalRanges = Mirror(reflecting: content).children.filter { $0.label == "some" }.map { $0.value } - for optionalRange in optionalRanges { - let ranges = Mirror(reflecting: optionalRange).children.filter { $0.label == "range" }.map { $0.value } - for (i, range) in ranges.dropFirst().enumerated() { - if let range = range as? Range { - captures.append( - Group( - location: Location( - start: range.lowerBound.utf16Offset(in: text), - end: range.upperBound.utf16Offset(in: text) - ), - value: String(text[range]), - type: String(reflecting: types[i]) - ) - ) - } else { - captures.append( - Group( - location: nil, - value: nil, - type: "Unknown" - ) - ) - } - } - } - } - } - } - } - return Match( - location: Location( - start: $0.range.lowerBound.utf16Offset(in: text), - end: $0.range.upperBound.utf16Offset(in: text) - ), - value: String(text[$0.range]), - captures: captures - ) - } - - let data = try JSONEncoder().encode(results) - print(String(data: data, encoding: .utf8) ?? "") - """# - - let standardInput = Pipe() - let standardOutput = Pipe() - let standardError = Pipe() - - let fileHandle = standardInput.fileHandleForWriting - fileHandle.write(script) - try fileHandle.close() - - let process = Process() - process.executableURL = URL(fileURLWithPath: "/usr/bin/swift") - process.arguments = ["-Xfrontend", "-enable-experimental-string-processing", "-enable-bare-slash-regex", "-"] - - process.standardInput = standardInput - process.standardOutput = standardOutput - process.standardError = standardError - - try process.run() - process.waitUntilExit() - - let stdoutData = standardOutput.fileHandleForReading.readDataToEndOfFile() - let stdout = String(data: stdoutData, encoding: .utf8) ?? "" - print(stdout) - - let stderrData = standardError.fileHandleForReading.readDataToEndOfFile() - let stderr = String(data: stderrData, encoding: .utf8) ?? "" - print(stderr, to:&IO.standardError) - } catch { - print("\(error)", to:&IO.standardError) - } - } -} - -struct IO { - static var standardError = FileHandle.standardError; -} - -extension FileHandle : TextOutputStream { - public func write(_ string: String) { - guard let data = string.data(using: .utf8) else { return } - self.write(data) - } -} diff --git a/Tests/RegexTests/BuilderTesterTests.swift b/Tests/RegexTests/BuilderTesterTests.swift deleted file mode 100644 index 561fc79..0000000 --- a/Tests/RegexTests/BuilderTesterTests.swift +++ /dev/null @@ -1,53 +0,0 @@ -import Foundation -import XCTest -@testable import BuilderTester - -class BuilderTesterTests: XCTestCase { - @MainActor - func testBuilderTest() throws { - CommandLine.arguments.removeAll() - CommandLine.arguments.append("BuilderTester") - CommandLine.arguments.append( - """ - let kind = Reference(Substring.self) - let date = Reference(Substring.self) - Regex { - Capture(as: kind) { - ChoiceOf { - "CREDIT" - "DEBIT" - } - } - OneOrMore(.whitespace) - Capture(as: date) { - Regex { - Repeat(1...2) { - One(.digit) - } - "/" - Repeat(1...2) { - One(.digit) - } - "/" - Repeat(count: 4) { - One(.digit) - } - } - } - } - """ - ) - CommandLine.arguments.append( - """ - KIND DATE INSTITUTION AMOUNT - ---------------------------------------------------------------- - CREDIT 03/01/2022 Payroll from employer $200.23 - CREDIT 03/03/2022 Suspect A $2,000,000.00 - DEBIT 03/03/2022 Ted's Pet Rock Sanctuary $2,000,000.00 - DEBIT 03/05/2022 Doug's Dugout Dogs $33.27 - DEBIT 06/03/2022 Oxford Comma Supply Ltd. £57.33 - """ - ) - try Main.main() - } -}