Run inline babel calls !129
2 files changed, +28 −0
Layout: unified · split
Sources/OrgCore/Compute/Babel.swift +22
| @@ -138,6 +138,9 @@ public enum Babel { | |||
| 138 | if let call = try callAt(context.caret, model: model, text: ns) { | 138 | if let call = try callAt(context.caret, model: model, text: ns) { |
| 139 | return located(plan(call.block, params: call.params, model: model, text: ns, options: options, location: call.location, name: call.name, refs: refs)) | 139 | return located(plan(call.block, params: call.params, model: model, text: ns, options: options, location: call.location, name: call.name, refs: refs)) |
| 140 | } | 140 | } |
| 141 | if let call = try inlineCallAt(context.caret, tree: context.tree, model: model, text: ns) { | ||
| 142 | return located(plan(call.block, params: call.params, model: model, text: ns, options: options, location: call.location, name: nil, inline: true, refs: refs)) | ||
| 143 | } | ||
| 141 | if let inline = try inlineAt(context.caret, tree: context.tree, model: model, text: ns) { | 144 | if let inline = try inlineAt(context.caret, tree: context.tree, model: model, text: ns) { |
| 142 | return located(plan(inline.block, params: inline.params, model: model, text: ns, options: options, location: inline.block.range, name: nil, inline: true, refs: refs)) | 145 | return located(plan(inline.block, params: inline.params, model: model, text: ns, options: options, location: inline.block.range, name: nil, inline: true, refs: refs)) |
| 143 | } | 146 | } |
| @@ -171,6 +174,25 @@ public enum Babel { | |||
| 171 | return (block, try Params(block: block, model: model, text: text, extra: extra), location, callName) | 174 | return (block, try Params(block: block, model: model, text: text, extra: extra), location, callName) |
| 172 | } | 175 | } |
| 173 | 176 | ||
| 177 | /// The inline `call_NAME[INSIDE](ARGS)[END]` at `offset`: like `#+CALL`, with the result | ||
| 178 | /// after the call. | ||
| 179 | static func inlineCallAt(_ offset: Int, tree: OrgTree, model: DocumentModel, text: NSString) throws -> (block: SrcBlockInfo, params: Params, location: Range<Int>)? { | ||
| 180 | var node = tree.root | ||
| 181 | var found: SyntaxNode? | ||
| 182 | while let child = node.child(containing: offset) { | ||
| 183 | if child.kind == .inlineBabelCall { found = child } | ||
| 184 | node = child | ||
| 185 | } | ||
| 186 | guard let object = found, let m = object.text.firstMatch(of: /^call_([^()\[\]\s]+)(?:\[([^\]]*)\])?\((.*?)\)(?:\[([^\]]*)\])?$/) else { return nil } | ||
| 187 | let name = String(m.1) | ||
| 188 | guard let block = model.srcBlocks.first(where: { $0.name == name }) else { throw Failure.message("Reference '\(name)' not found in this buffer") } | ||
| 189 | var extra: [[(String, String)]] = [] | ||
| 190 | if let inside = m.2 { extra.append(Params.parse(String(inside))) } | ||
| 191 | extra.append(splitArguments(String(m.3)).map { (":var", $0) }) | ||
| 192 | if let end = m.4 { extra.append(Params.parse(String(end))) } | ||
| 193 | return (block, try Params(block: block, model: model, text: text, extra: extra), object.range) | ||
| 194 | } | ||
| 195 | |||
| 174 | /// Call arguments split on commas outside quotes and parentheses. | 196 | /// Call arguments split on commas outside quotes and parentheses. |
| 175 | static func splitArguments(_ s: String) -> [String] { | 197 | static func splitArguments(_ s: String) -> [String] { |
| 176 | var parts: [String] = [] | 198 | var parts: [String] = [] |
Tests/OrgCoreTests/BabelTests.swift +6
| @@ -196,6 +196,12 @@ struct BabelCallTests { | |||
| 196 | ("Text src_sh[:results raw]{echo raw} end.\n", "src_sh"), | 196 | ("Text src_sh[:results raw]{echo raw} end.\n", "src_sh"), |
| 197 | ("Text src_python{return 6*7} end.\n", "src_python"), | 197 | ("Text src_python{return 6*7} end.\n", "src_python"), |
| 198 | ("Text src_sh[:var x=3]{echo $x} end.\n", "src_sh"), | 198 | ("Text src_sh[:var x=3]{echo $x} end.\n", "src_sh"), |
| 199 | (named + "Inline call_double(n=6) here.\n", "call_"), | ||
| 200 | (named + "Inline call_double() here.\n", "call_"), | ||
| 201 | (named + "Inline call_double(n=6)[:results raw] here.\n", "call_"), | ||
| 202 | (named + "Inline call_double[:results verbatim](n=1) here.\n", "call_"), | ||
| 203 | (named + "Inline call_double(n=2) {{{results(=0=)}}} here.\n", "call_"), | ||
| 204 | (named + "Inline call_double(n=2) and call_double(n=3) here.\n", "call_double(n=3"), | ||
| 199 | ] | 205 | ] |
| 200 | 206 | ||
| 201 | @Test(.enabled(if: ProcessInfo.processInfo.environment["ORGSTAR_SKIP_ORACLE"] == nil)) | 207 | @Test(.enabled(if: ProcessInfo.processInfo.environment["ORGSTAR_SKIP_ORACLE"] == nil)) |