ek9_surround_with

Folds a contiguous line range under an if / if-else / try-catch / try-catch-finally / for-range / while head, re-indenting the block per EK9's brace-free rules; answers status and edits[] (one REPLACE carrying the head + the re-indented lines, one DELETE per absorbed line).

Category: Editor · Compare: Surround With… (IntelliJ — Cmd+Alt+T)

When to use it

'Wrap those lines in an if on count > 0' is one call with file, fromText (the block's first line as written), toText (its last), surroundType:'if', condition:'count > 0' - the tool owns the re-indent. Use it on a contiguous range of WHOLE statements at one indent level that should run conditionally, loop, or be exception-handled.

When not to use it

Details

Head text you pass (condition for if/if-else/while, rangeExpression for for-range, exceptionType/exceptionVariable for try-catch) is parsed alone first - a text that does not parse is status:error with nothing written - then emitted verbatim. An omitted head is an opaque placeholder for the caller to edit: `if` inserts `surroundGuard <- Boolean(true)` then `if surroundGuard? //AI:`, `while` inserts `loopGuard <- Boolean(false)` then `while loopGuard //AI:`, `for-range` inserts `for i in 1 ... 10 //AI:` (a bare `true` would trip E07390 pointless-condition). Wrapped lines are re-indented +2 spaces; the head line(s) sit at the block's current indent; a line range outside the file or endLine < startLine is a hard error.

Arguments

ArgumentTypeRequiredWhat it is
conditionstringif / if-else / while: the condition source text (e.g. 'count > 0', 'name?'), emitted verbatim. Omitted: an opaque placeholder guard with an //AI: marker to replace.
endLineintegerOr the last line of the selection (1-based, inclusive).
exceptionTypestringtry-catch / try-catch-finally: the caught type (default Exception).
exceptionVariablestringtry-catch / try-catch-finally: the handler's variable name (default ex).
filestringyesWorkspace-relative path to the .ek9 source file containing the lines to wrap.
fromTextstringThe block's FIRST line exactly as written (indentation ignored) - instead of counting startLine. Must name one line; add more of it when it occurs twice.
rangeExpressionstringfor-range: the text after 'for i in' (e.g. '1 ... 10', 'items'), or a whole 'item in items' clause. Omitted: 'for i in 1 ... 10 //AI: Replace range'.
startLineintegerOr the first line of the selection (1-based) - an IDE selection.
surroundTypestring: if | if-else | try-catch | try-catch-finally | for-range | whileyesThe wrapper: if, if-else, try-catch, try-catch-finally, for-range or while.
toTextstringThe block's LAST line as written - the first line matching it at or after fromText. Omit it for a one-line block.

It also takes the arguments every tool takes.

Recorded calls

Real calls, recorded against small projects and checked on every build - a changed answer fails it. 3 of the 4 recorded are shown.

Surround with condition does not parse

Request

{
  "condition" : "count >",
  "endLine" : 8,
  "file" : "Hello.ek9",
  "startLine" : 8,
  "surroundType" : "if"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ ],
  "error" : {
    "message" : "condition does not parse as EK9: extraneous indentation expecting valid statement or expression near 'indentation' - fix the text, or omit it for a placeholder head"
  },
  "meta" : {
    "serverMs" : "<timing>"
  },
  "status" : "error",
  "summary" : "condition does not parse as EK9: extraneous indentation expecting valid statement or expression near 'indentation' - fix the text, or omit it for a placeholder head",
  "wouldBeDiagnostics" : [ ],
  "written" : false
}

Surround with from text apply

Request

{
  "condition" : "count > 0",
  "file" : "Hello.ek9",
  "fromText" : "stdout.println($count)",
  "surroundType" : "if",
  "toText" : "stdout.println($count)"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      if count > 0\n        stdout.println($count)",
    "before" : "      stdout.println($count)",
    "endLine" : 8,
    "file" : "Hello.ek9",
    "startLine" : 8,
    "type" : "replace"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "resolvedPath" : "<workspace-root>/Hello.ek9",
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "applied",
  "summary" : "Surrounded lines 8-8 with if",
...

Cut short here: 4 more lines. The whole recorded call.

Surround with if condition apply

Request

{
  "condition" : "count > 0",
  "endLine" : 8,
  "file" : "Hello.ek9",
  "startLine" : 8,
  "surroundType" : "if"
}

Response

{
  "conflicts" : [ ],
  "edits" : [ {
    "after" : "      if count > 0\n        stdout.println($count)",
    "before" : "      stdout.println($count)",
    "endLine" : 8,
    "file" : "Hello.ek9",
    "startLine" : 8,
    "type" : "replace"
  } ],
  "meta" : {
    "serverMs" : "<timing>"
  },
  "resolvedPath" : "<workspace-root>/Hello.ek9",
  "risk" : {
    "crossesModuleBoundary" : false,
    "estimatedSeverity" : "trivial",
    "fileCount" : 1,
    "lineCount" : 1,
    "touchesPublicApi" : false,
    "touchesTests" : false
  },
  "status" : "applied",
  "summary" : "Surrounded lines 8-8 with if",
...

Cut short here: 4 more lines. The whole recorded call.

See also