| @@ -190,7 +190,7 @@ public enum Babel { |
| 190 | 190 | guard let m = line.firstMatch(of: #/(?i)^[ \t]*#\+CALL:[ \t]*([^\s(\[]+)(?:\[([^\]]*)\])?\((.*?)\)[ \t]*(.*?)[ \t]*\n?$/#) else { return nil } |
| 191 | 191 | let name = String(m.1) |
| 192 | 192 | guard let block = model.srcBlocks.first(where: { $0.name == name }) else { throw Failure.message("Reference '\(name)' not found in this buffer") } |
| 193 | | var extra = [lobDefaults] |
| 193 | var extra = [lobDefaults] + callProperties(block, at: lineRange.location, model: model) |
| 194 | 194 | if let inside = m.2 { extra.append(Params.parse(String(inside))) } |
| 195 | 195 | extra.append(splitArguments(String(m.3)).map { (":var", $0) }) |
| 196 | 196 | if !m.4.isEmpty { extra.append(Params.parse(String(m.4))) } |
| @@ -216,13 +216,20 @@ public enum Babel { |
| 216 | 216 | guard let object = found, let m = object.text.firstMatch(of: /^call_([^()\[\]\s]+)(?:\[([^\]]*)\])?\((.*?)\)(?:\[([^\]]*)\])?$/) else { return nil } |
| 217 | 217 | let name = String(m.1) |
| 218 | 218 | guard let block = model.srcBlocks.first(where: { $0.name == name }) else { throw Failure.message("Reference '\(name)' not found in this buffer") } |
| 219 | | var extra = [lobDefaults] |
| 219 | var extra = [lobDefaults] + callProperties(block, at: object.range.lowerBound, model: model) |
| 220 | 220 | if let inside = m.2 { extra.append(Params.parse(String(inside))) } |
| 221 | 221 | extra.append(splitArguments(String(m.3)).map { (":var", $0) }) |
| 222 | 222 | if let end = m.4 { extra.append(Params.parse(String(end))) } |
| 223 | 223 | return (block, try Params(block: block, model: model, text: text, extra: extra), object.range) |
| 224 | 224 | } |
| 225 | 225 | |
| 226 | /// The `header-args` properties where a call is, in the called block's language, which |
| 227 | /// `org-babel-lob-get-info` puts after `lobDefaults`. |
| 228 | static func callProperties(_ block: SrcBlockInfo, at location: Int, model: DocumentModel) -> [[(String, String)]] { |
| 229 | let heading = model.headings.lastIndex { $0.headingRange.lowerBound <= location } |
| 230 | return Params.propertyLayers(language: block.language ?? "", heading: heading, model: model) |
| 231 | } |
| 232 | |
| 226 | 233 | /// `org-babel-default-lob-header-args`, over the called block's own header arguments. |
| 227 | 234 | static let lobDefaults = [(":exports", "results")] |
| 228 | 235 | |
| @@ -246,7 +253,9 @@ public enum Babel { |
| 246 | 253 | if line.range(of: "(?i)^[ \\t]*#\\+CALL:", options: .regularExpression) != nil { |
| 247 | 254 | call = (try? callAt(offset, model: model, text: text))?.params |
| 248 | 255 | } else if tree.root.descendants().contains(where: { $0.kind == .inlineBabelCall && $0.range.lowerBound == offset }) { |
| 249 | | call = (try? inlineCallAt(offset, tree: tree, model: model, text: text))?.params |
| 256 | // `org-babel-remove-result` only takes away `#+RESULTS:`, so an inline call's |
| 257 | // `{{{results(...)}}}` stays whatever `:exports` says. |
| 258 | return "results" |
| 250 | 259 | } else if let inline = try? inlineAt(offset, tree: tree, model: model, text: text), inline.block.range.lowerBound == offset { |
| 251 | 260 | return value(inline.params, language: inline.block.language) |
| 252 | 261 | } else { |
| @@ -924,22 +933,7 @@ public enum Babel { |
| 924 | 933 | init(block: SrcBlockInfo, model: DocumentModel, text: NSString, defaults: [(String, String)] = [], extra: [[(String, String)]] = [], |
| 925 | 934 | inline: Bool = false) throws { |
| 926 | 935 | var layers: [[(String, String)]] = [defaults] |
| 927 | | let language = block.language ?? "" |
| 928 | | // `org-babel-params-from-properties`: the inherited `header-args`, then the inherited |
| 929 | | // `header-args:LANG`, each the nearest value with `+` additions after it. |
| 930 | | var levels = [model.fileProperties] |
| 931 | | if let heading = block.heading { |
| 932 | | levels += (model.ancestors(of: heading).reversed() + [heading]).map { model.headings[$0].properties } |
| 933 | | } |
| 934 | | for key in ["header-args", "header-args:\(language)"] { |
| 935 | | var value: String? |
| 936 | | for entries in levels { |
| 937 | | for entry in entries where entry.key.lowercased() == key { |
| 938 | | value = entry.additive ? [value, entry.value].compactMap { $0 }.joined(separator: " ") : entry.value |
| 939 | | } |
| 940 | | } |
| 941 | | if let value { layers.append(Params.parse(value)) } |
| 942 | | } |
| 936 | layers += Params.propertyLayers(language: block.language ?? "", heading: block.heading, model: model) |
| 943 | 937 | let firstLine = inline ? "" : text.substring(with: text.lineRange(for: NSRange(location: block.range.lowerBound, length: 0))) |
| 944 | 938 | if let r = firstLine.range(of: "(?i)#\\+begin_src[ \\t]+\\S+", options: .regularExpression) { |
| 945 | 939 | var rest = String(firstLine[r.upperBound...]).trimmingCharacters(in: .whitespacesAndNewlines) |
| @@ -993,6 +987,25 @@ public enum Babel { |
| 993 | 987 | } |
| 994 | 988 | } |
| 995 | 989 | |
| 990 | /// `org-babel-params-from-properties` under `heading`, or before any: the inherited |
| 991 | /// `header-args`, then the inherited `header-args:LANG`, each the nearest value with `+` |
| 992 | /// additions after it. |
| 993 | static func propertyLayers(language: String, heading: Int?, model: DocumentModel) -> [[(String, String)]] { |
| 994 | var levels = [model.fileProperties] |
| 995 | if let heading { |
| 996 | levels += (model.ancestors(of: heading).reversed() + [heading]).map { model.headings[$0].properties } |
| 997 | } |
| 998 | return ["header-args", "header-args:\(language)"].compactMap { key in |
| 999 | var value: String? |
| 1000 | for entries in levels { |
| 1001 | for entry in entries where entry.key.lowercased() == key { |
| 1002 | value = entry.additive ? [value, entry.value].compactMap { $0 }.joined(separator: " ") : entry.value |
| 1003 | } |
| 1004 | } |
| 1005 | return value.map(Params.parse) |
| 1006 | } |
| 1007 | } |
| 1008 | |
| 996 | 1009 | /// `org-babel-parse-header-arguments`: split before each `:key` outside quotes and |
| 997 | 1010 | /// parentheses. |
| 998 | 1011 | /// A Lisp string's contents as `read` gives them. |