├── CheckSyntax ├── ABL.sublime-build.example ├── ABL.sublime-settings └── syntax.p ├── OpenEdge ABL.sublime-package ├── ABL.JSON-tmLanguage ├── ABL.sublime-build ├── ABL.tmLanguage ├── ABL_Comments.JSON-tmPreferences ├── ABL_Comments.tmPreferences ├── AblUppercase.py ├── Cobalt.tmTheme ├── Default (Linux).sublime-keymap ├── Default (Windows).sublime-keymap ├── Espresso Libre.tmTheme ├── abl.p ├── abl.py ├── comment.sublime-snippet ├── debug.sublime-snippet ├── defineparam.sublime-snippet ├── defpar-Int64.sublime-snippet ├── defpar-character.sublime-snippet ├── defpar-date.sublime-snippet ├── defpar-decimal.sublime-snippet ├── defpar-handle.sublime-snippet ├── defpar-integer.sublime-snippet ├── defpar-logical.sublime-snippet ├── defpar-longchar.sublime-snippet ├── defvar-Int64.sublime-snippet ├── defvar-character.sublime-snippet ├── defvar-date.sublime-snippet ├── defvar-decimal.sublime-snippet ├── defvar-handle.sublime-snippet ├── defvar-integer.sublime-snippet ├── defvar-logical.sublime-snippet ├── defvar-longchar.sublime-snippet ├── function forward.sublime-snippet ├── function.sublime-snippet ├── header.sublime-snippet ├── input.sublime-snippet ├── procedure.sublime-snippet └── temp-table.sublime-snippet ├── README.md └── dist └── OpenEdge ABL.sublime-package /CheckSyntax/ABL.sublime-build.example: -------------------------------------------------------------------------------- 1 | { 2 | "shell_cmd": "C:\\Progress\\102B\\bin\\_progres.exe -1 -b -pf C:\\Progress\\102B\\startup.pf -p C:\\path\\to\\syntax.p -param \"$file\"", 3 | "file_regex": "^(?:ERROR|WARNING]) File:'(.+)' Row:([0-9]+) Col:([0-9]+) Error:[0-9]+ Message:(.*)$" 4 | } -------------------------------------------------------------------------------- /CheckSyntax/ABL.sublime-settings: -------------------------------------------------------------------------------- 1 | { 2 | "extensions": 3 | [ 4 | "p", 5 | "i", 6 | "def", 7 | "ds", 8 | "w", 9 | "cls", 10 | "fct" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /CheckSyntax/syntax.p: -------------------------------------------------------------------------------- 1 | /* 2 | Programme pour faire un Check Syntax en dehors d'Open Edge 3 | 4 | Utilisation: 5 | C:\Progress\102B\bin\_progres.exe -1 -b -pf C:\Progress\102B\startup.pf.alternatifs\startup_.net.pf -p C:\path\to\syntax.p -param "C:\program_to_check.p" 6 | */ 7 | 8 | DEFINE VARIABLE ch_prog AS CHARACTER NO-UNDO. 9 | DEFINE VARIABLE ch_mess AS CHARACTER NO-UNDO. 10 | DEFINE VARIABLE i AS INTEGER NO-UNDO. 11 | 12 | /* Extracts the parameters */ 13 | ASSIGN ch_prog = ENTRY( 1, SESSION:PARAMETER ). 14 | IF NUM-ENTRIES(SESSION:PARAMETER) >= 2 THEN DO : 15 | ASSIGN PROPATH = PROPATH + ":" + ENTRY( 2, SESSION:PARAMETER ). 16 | END. 17 | 18 | /* Compile without saving */ 19 | COMPILE VALUE( ch_prog ) SAVE=NO NO-ERROR. 20 | 21 | /* If there are compilation messages */ 22 | IF COMPILER:NUM-MESSAGES > 0 THEN DO: 23 | 24 | ASSIGN ch_mess = "". 25 | 26 | /* For each messages */ 27 | DO i = 1 TO COMPILER:NUM-MESSAGES: 28 | 29 | /* Generate an error line */ 30 | ASSIGN ch_mess = 31 | SUBSTITUTE( "&1 File:'&2' Row:&3 Col:&4 Error:&5 Message:&6", 32 | IF COMPILER:WARNING = TRUE THEN "WARNING" ELSE "ERROR", 33 | COMPILER:GET-FILE-NAME ( i ), 34 | COMPILER:GET-ROW ( i ), 35 | COMPILER:GET-COLUMN ( i ), 36 | COMPILER:GET-NUMBER ( i ), 37 | COMPILER:GET-MESSAGE ( i ) 38 | ) 39 | . 40 | 41 | /* display the message to the standard output */ 42 | PUT UNFORMATTED ch_mess SKIP. 43 | END. 44 | END. 45 | ELSE DO : 46 | 47 | /* display to the standard output */ 48 | PUT UNFORMATTED "SUCCESS: Syntax is Correct." SKIP. 49 | END. 50 | 51 | /* End of program */ 52 | QUIT. -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/ABL.JSON-tmLanguage: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OpenEdge ABL", 3 | "scopeName": "source.abl", 4 | "fileTypes": ["p","i","cls","fct","def","ds"], 5 | "patterns": [ 6 | { 7 | "match": "comment:", 8 | "name": "comment.testing" 9 | }, 10 | { 11 | "comment": "regular comment block. todo - require space when compile, if yes then change to not highlight", 12 | "begin": "/\\*", 13 | "end": "\\*/", 14 | "name": "comment.block.source.abl", 15 | "patterns": [ 16 | { 17 | "begin": "/\\*", 18 | "end": "\\*/", 19 | "name": "comment.block.source.abl" 20 | } 21 | ] 22 | }, 23 | 24 | { 25 | "match": "constant:", 26 | "name": "constant.testing" 27 | }, 28 | { "include": "#constantHTMLColors" }, 29 | { "include": "#constantNumbers" }, 30 | { 31 | "comment": "boolean conditions.", 32 | "match": "(?i)\\s(=|eq|<|lt|>|gt|<=|le|>=|ge|<>)\\s", 33 | "name": "constant.character.source.abl" 34 | }, 35 | { 36 | "comment": "math operators.", 37 | "match": "(\\+|\\-|\\*|/)", 38 | "name": "constant.character.math.operator.source.abl" 39 | }, 40 | { 41 | "comment": "constants - operators - simple list. ", 42 | "match": "(?i)\\b(and|as|false|no(?!-)|not|of|on|or|to|true|yes)\\b", 43 | "name": "constant.language.source.abl" 44 | }, 45 | 46 | { 47 | "name": "entity.testing", 48 | "match": "entity:" 49 | }, 50 | { 51 | "comment": "constructor/destructor method", 52 | "match": "(?i)(constructor|destructor)\\s+((private|protected|public)\\s+)?((static)\\s+)?([a-z]+)", 53 | "name": "meta.function.source.abl", 54 | "captures": { 55 | "1": { "name": "entity.name.function.abl" }, 56 | "2": { "name": "storage.modifier.abl" }, 57 | "3": { "name": "storage.modifier.abl" }, 58 | "4": { "name": "entity.name.hidden.abl"} 59 | } 60 | }, 61 | { 62 | "comment": "function", 63 | "match": "(?i)(function)\\s+([a-z0-9_-]+)\\s+(returns)\\s+(char(?:acter)?|datetime-tz|datetime|date|decimal|int(?:eger)?|int64|logical|longchar|memptr)(\\s+)?(\\(|\\n)", 64 | "name": "meta.function.source.abl", 65 | "captures": { 66 | "1": { "name": "keyword.control.source.abl" }, 67 | "2": { "name": "entity.name.function.abl" }, 68 | "3": { "name": "keyword.other.source.abl" }, 69 | "4": { "name": "storage.type.datatype.abl" } 70 | } 71 | }, 72 | { 73 | "comment": "main block", 74 | "match": "(?i)(main(\\-)?block):", 75 | "name": "meta.function.source.abl", 76 | "captures": { 77 | "1": { "name": "entity.name.function.abl"} 78 | } 79 | }, 80 | { 81 | "comment": "method", 82 | "begin": "(?i)(method)\\s+((override|private|protected|public)\\s+)?((static)\\s+)?([a-zA-Z0-9.]+)\\s+([a-zA-Z]+)", 83 | "beginCaptures": { 84 | "1": { "name": "keyword.control.source.abl" }, 85 | "2": { "name": "storage.modifier.abl" }, 86 | "3": { "name": "storage.type.datatype.abl" }, 87 | "4": { "name": "entity.name.function.abl" } 88 | }, 89 | "patterns": [ 90 | { "include": "#constantNumbers" }, 91 | { "include": "#dataTypes" }, 92 | { "include": "#defineKeywords" }, 93 | { "include": "#fileField" }, 94 | { "include": "#keywordAsLike" }, 95 | { "include": "#variableNames" } 96 | ], 97 | "end": "\\):" 98 | }, 99 | { 100 | "comment": "procedure", 101 | "match": "(?i)(procedure)\\s+([a-z0-9\\/_-]+)(:|\\(|\\n)", 102 | "name": "meta.function.source.abl", 103 | "captures": { 104 | "1": { "name": "keyword.control.source.abl" }, 105 | "2": { "name": "entity.name.function.abl" } 106 | } 107 | }, 108 | 109 | { 110 | "match": "exception:", 111 | "name": "support.type.exception.testing" 112 | }, 113 | 114 | { 115 | "match": "invalid:", 116 | "name": "invalid.testing" 117 | }, 118 | 119 | { 120 | "match": "keyword:", 121 | "name": "keyword.testing" 122 | }, 123 | { 124 | "comment": "Accumulate keywords", 125 | "match": "(?i)\\b(accumulate|accum|averate|count|maximum|minimum|total|sub-average|sub-count|sub-maximum|sub-minimum|sub-total|lable|by)\\b", 126 | "name": "keyword.other.class.source.abl" 127 | }, 128 | { 129 | "comment": "Case keywords", 130 | "match": "(?i)\\b(|case|when|otherwise)\\b", 131 | "name": "keyword.other.class.source.abl" 132 | }, 133 | { 134 | "comment": "ends keywords.", 135 | "match": "(?i)(end)(\\s+(case|class|constructor|destructor|finally|function|interface|method|procedure))?\\.", 136 | "captures": { 137 | "1": {"name": "keyword.control.end.source.abl"}, 138 | "2": {"name": "keyword.control.end.source.abl"} 139 | } 140 | }, 141 | { 142 | "comment": "Find & For keywords", 143 | "match": "(?i)\\b(can-find(\\((first|last|prev))?|find\\s+(first|last|prev)?|for\\s+(each|first|last)|by|descending|exclusive-lock|exclusive|no-lock|no-wait|of|share-lock|transaction|use-index|using|where|while)\\b", 144 | "name": "keyword.other.class.source.abl" 145 | }, 146 | { 147 | "comment": "format & frame keywords", 148 | "match": "(?i)\\b(as|attr-space|auto-return|bgcolor|blank|cancel-button|centered|colon|column-label|columns|column|context-help|context-help-file|dcolor|deblank|default-buttone|disable-auto-zap|down|fgcolor|font|format|frame|help|keep-tab-order|label|like|no-attr-space|no-box|no-help|no-hide|no-labels|no-tab-stop|no-underline|no-validate|overlay|page-bottom|page-top|pfcolor|retain|row|screen-id|stream-io|scrollable|scroll|side-labels|skip|stream|three-d|top-only|to|use-dect-exps|use-text|v6frame|validate|view-as dialog-box|width|with)\\b", 149 | "name": "keyword.other.frames.source.abl" 150 | }, 151 | { 152 | "comment": "message keywords", 153 | "match": "(?i)\\b(message|auto-return|buttons|color|in window|set|skip|title|update|view-as alert-box)\\b", 154 | "name": "keyword.other.class.source.abl" 155 | }, 156 | { 157 | "comment": "on block keywords", 158 | "match": "(?i)\\b(on|endkey|error|quit|stop|anywhere|leave|next|no-apply|override|persistent run|retry|return|revert|undo)\\b", 159 | "name": "keyword.other.class.source.abl" 160 | }, 161 | { 162 | "comment": "output keywords", 163 | "match": "(?i)\\b(output|append|binary|close|collate|convert|echo|keep-messages|landscape|map|no-convert|no-echo|no-map|num-copies|paged|page-size|portrait|printer|stream|terminal|through|to|unbuffered|value)\\b", 164 | "name": "keyword.other.class.source.abl" 165 | }, 166 | { 167 | "comment": "put keywords", 168 | "match": "(?i)\\b(put|attr-space|color|column|control|cursor|format|no-attr-space|off|row|skip|screen|stream|unformatted)\\b", 169 | "name": "keyword.other.class.source.abl" 170 | }, 171 | { 172 | "comment": "Other keywords - A - B", 173 | "match": "(?i)\\b(absolute|add-interval|alias|ambiguous|apply|asc|assign|at|available|begins|bell|browse|buffer)\\b", 174 | "name": "keyword.other.class.source.abl" 175 | }, 176 | { 177 | "comment": "Other keywords - C", 178 | "match": "(?i)\\b(call|can-do|can-query|can-set|caps|cast|catch|class|choose|chr|clear|close|codepage-convert|color|combo-box|compare|compile|compiler|save|connect|connected|count-of|create|current-changed|current-language|current-result-row|current-value)\\b", 179 | "name": "keyword.other.class.source.abl" 180 | }, 181 | { 182 | "comment": "Other keywords - D", 183 | "match": "(?i)\\b(dataservers|datetime-tz|datetime|date|daydbcodepage|dbcollation|dbname|dbparam|dbrestrictions|dbtaskid|dbtype|dbversion|decimal|delete|delimiter|dictionary|disable|disconnect|display|do|down|dynamic-function|dynamic-new)\\b", 184 | "name": "keyword.other.class.source.abl" 185 | }, 186 | { 187 | "comment": "Other keywords - E - F", 188 | "match": "(?i)\\b(editing|editor|empty temp-table|enable|encode|entered|entry|etime|exp|export|extent|fill|finally|final|first-of|first|form)\\b", 189 | "name": "keyword.other.class.source.abl" 190 | }, 191 | { 192 | "comment": "Other keywords - G", 193 | "match": "(?i)\\b(gateways|get|get-bits|get-byte|get-byte-order|get-bytes|get-codepages|get-collations|get-double|get-float|get-key-value|get-long|get-pointer-value|get-short|get-size|get-string|get-unsigned-short|go-pending)\\b", 194 | "name": "keyword.other.class.source.abl" 195 | }, 196 | { 197 | "comment": "Other keywords - H - I", 198 | "match": "(?i)\\b(hex-encode|hide|if|then|else|image|implements|import|index|inherits|input\\s+(clear|close|from|through)?|insert|integer|interface|interval|is-attr-space|is-lead-byte)\\b", 199 | "name": "keyword.other.class.source.abl" 200 | }, 201 | { 202 | "comment": "Other keywords - K - L", 203 | "match": "(?i)\\b(kblabel|keycode|keyfunction|keylable|keyword|keyword-all|last|lastkey|last-of|lc|ldbname|leave|left-trim|length|library|lin-counter|list-(events|query-attrs|set-attrs|widgets)|load|load-picture|locked|log|lookup)\\b", 204 | "name": "keyword.other.class.source.abl" 205 | }, 206 | { 207 | "comment": "Other keywords - M - N", 208 | "match": "(?i)\\b(matches|maximum|max|md5-digest|member|message-lines|minimum|modulo|month|new|next|next-prompt|next-value|num-aliases|num-dbs|num-entries|num-results)\\b", 209 | "name": "keyword.other.class.source.abl" 210 | }, 211 | { 212 | "comment": "Other keywords - O", 213 | "match": "(?i)\\b(open query|opsys|os-(append|command|copy|create-dir|delete|drives|error|getenv|rename)|overlay)\\b", 214 | "name": "keyword.other.class.source.abl" 215 | }, 216 | { 217 | "comment": "Other keywords - P", 218 | "match": "(?i)\\b(page|page-number|page-size|pause|pdbname|preselect|proc-handle|proc-status|process events|program-name|projpt-for|promsgs|propath|proversion|publsih|put cursor|put screen|put-(bits|bytes|byte|double|float|key-value|long|session|short|string|unsigned-short))\\b", 219 | "name": "keyword.other.class.source.abl" 220 | }, 221 | { 222 | "comment": "Other keywords - U", 223 | "match": "(?i)\\b(use-widget-pool|using)\\b", 224 | "name": "keyword.other.class.source.abl" 225 | }, 226 | { 227 | "comment": "class keywords.", 228 | "match": "(?i)\\b(super)\\b", 229 | "name": "keyword.other.class.source.abl" 230 | }, 231 | { 232 | "comment": "control keywords.", 233 | "match": "(?i)\\b(repeat|return|then|transaction:?|when)\\b", 234 | "name": "keyword.control.source.abl" 235 | }, 236 | { 237 | "comment": "general keywords.", 238 | "match": "(?i)\\b(object|output\\s+(close|thru|through|to)|put(\\sunformatted)?|replace|routine-level|substitute|substring|throw|triggers for load of|trim|undo|update|valid-handle|valid-object)\\b", 239 | "name": "keyword.other.statement.source.abl" 240 | }, 241 | { 242 | "comment": "query keywords.", 243 | "match": "(?i)\\b(query|table|temp-table)\\b", 244 | "name": "keyword.other.statement.source.abl" 245 | }, 246 | { 247 | "comment": "buffer attributes", 248 | "match": "(?i):(adm-data|available|can-create|can-delete|can-read|can-write|current-changed|dbname|handle|locked|name|new|next-sibling|num-fields|primary|private-data|recid|record-length|rowid|table|table-handle|table-number|type|unique-id)\\b", 249 | "name": "keyword.other.statement.source.abl" 250 | }, 251 | { 252 | "comment": "buffer methods", 253 | "match": "(?i):(buffer-compare|buffer-copy|buffer-create|buffer-delete|buffer-field|buffer-release|empty-temp-table|find-by-rowid|index-information|raw-transfer)\\b", 254 | "name": "keyword.other.statement.source.abl" 255 | }, 256 | { 257 | "comment": "buffer field attributes", 258 | "match": "(?i):(adm-data|buffer-handle|buffer-name|buffer-value|can-read|can-write|case-sensitive|column-label|data-type|dbname|extent|format|handle|mandatory|name|position|private-data|read-only|string-value|table|type|unique-id|validate-expression|validate-message|width-chars)\\b", 259 | "name": "keyword.other.statement.source.abl" 260 | }, 261 | { 262 | "comment": "error and error-statu attributes & methods", 263 | "match": "(?i)(error-status|error|no-error|num-message|type|get-message|get-number)|(:(apperror|syserror|getMessage|numMessages|returnValue))\\b", 264 | "name": "keyword.other.statement.source.abl" 265 | }, 266 | { 267 | "comment": "query attributes", 268 | "match": "(?i):(adm-data|cache|current-result-row|handle|index-information|is-open|name|num-buffers|num-results|prepare-string|private-data|query-off-end|skip-deleted-record|type)\\b", 269 | "name": "keyword.other.statement.source.abl" 270 | }, 271 | { 272 | "comment": "query methods", 273 | "match": "(?i):(add-buffer|create-result-list-entry|delete-result-list-entry|get-buffer-handle|get-current|get-first|get-last|get-next|get-prev|set-buffers|query-close|query-open|query-prepare|reposition-backward|reposition-forward|reposition-to-row|reposition-to-rowid)\\b", 274 | "name": "keyword.other.statement.source.abl" 275 | }, 276 | { 277 | "comment": "temp-table attributes & methods", 278 | "match": "(?i):(default-buffer-handle|name|prepared|primary|undo|add-fields-from|add-index-field|add-like-field|add-like-index|add-new-field|add-new-index|clear|create-like|temp-table-prepare)\\b", 279 | "name": "keyword.other.statement.source.abl" 280 | }, 281 | 282 | 283 | { 284 | "match": "punctuation:", 285 | "name": "punctuation.string.testing" 286 | }, 287 | 288 | { 289 | "match": "storage:", 290 | "name": "storage.testing" 291 | }, 292 | { 293 | "comment": "buffer", 294 | "match": "(?i)(def(?:ine)?\\s+buffer)\\s+(b|bf)([A-Z][a-zA-Z0-9-]+)\\s+(for)\\s+([a-zA-Z0-9-]+)", 295 | "captures": { 296 | "1": {"name": "keyword.other.source.abl"}, 297 | "2": {"name": "variable.property.abl"}, 298 | "3": {"name": "variable.property.abl"}, 299 | "4": {"name": "constant.other.source.abl"}, 300 | "5": {"name": "text.other.source.abl"}, 301 | "6": {"name": "text.other.source.abl"} 302 | } 303 | }, 304 | { 305 | "comment": "parameters - for functions and methods", 306 | "match": "(?i)(input)\\s+(i|ip)([A-Z][a-zA-Z0-9]+)\\s+(as\\s+(char(?:acter)?|datetime-tz|datetime|date|decimal|int(?:eger)?|int64|logical|longchar|memptr)|(like)\\s+([a-zA-Z0-9-]+\\.[a-zA-Z0-9_-]+))", 307 | "captures": { 308 | "1": {"name": "keyword.other.source.abl"}, 309 | "2": {"name": "variable.other.synergy.abl"}, 310 | "3": {"name": "variable.other.synergy.abl"}, 311 | "4": {"name": "constant.other.source.abl"}, 312 | "5": {"name": "storage.type.source.abl"}, 313 | "6": {"name": "constant.other.source.abl"}, 314 | "7": {"name": "text.other.source.abl"} 315 | } 316 | }, 317 | { 318 | "comment": "parameters - for procedures", 319 | "match": "(?i)(def(?:ine)?)\\s+(input|output|input-output)\\s+(parameter)\\s+([a-z0-9\\-_]+)\\s+(as)\\s+([a-z\\-]+)(\\s*no-undo)?", 320 | "captures": { 321 | "1": {"name": "keyword.other.source.abl"}, 322 | "2": {"name": "keyword.other.source.abl"}, 323 | "3": {"name": "keyword.other.source.abl"}, 324 | "4": {"name": "variable.property.abl"}, 325 | "5": {"name": "keyword.other.source.abl"}, 326 | "6": {"name": "storage.type.source.abl"}, 327 | "7": {"name": "keyword.other.source.abl"} 328 | } 329 | }, 330 | { 331 | "comment": "property", 332 | "begin": "(?i)(def(?:ine)?\\s+property)", 333 | "beginCaptures": { 334 | "1": {"name": "keyword.other.source.abl"} 335 | }, 336 | "patterns": [ 337 | { 338 | "match": "(?i)(get)", 339 | "name": "keyword.other.source.abl" 340 | }, 341 | { "include": "#dataTypes" }, 342 | { "include": "#defineKeywords" }, 343 | { "include": "#fileField" }, 344 | { "include": "#keywordAsLike" }, 345 | { "include": "#objectStatus" }, 346 | { "include": "#variableNames" } 347 | ], 348 | "end": "(?i)(set)\\.", 349 | "endCaptures": { 350 | "1": {"name": "keyword.other.source.abl"} 351 | } 352 | }, 353 | { 354 | "comment": "query", 355 | "match": "(?i)(def(?:ine)?\\s+query)\\s+((q|qy)[A-Z][a-zA-Z0-9-]+)\\s+(for)\\s+([a-zA-Z0-9-]+)", 356 | "captures": { 357 | "1": {"name": "keyword.other.source.abl"}, 358 | "2": {"name": "variable.property.abl"}, 359 | "3": {"name": "variable.property.abl"}, 360 | "4": {"name": "constant.other.source.abl"}, 361 | "5": {"name": "text.other.source.abl"} 362 | } 363 | }, 364 | { 365 | "comment": "stream", 366 | "match": "(?i)(def(?:ine)?\\s+stream)\\s+([a-zA-Z0-9]+)\\.", 367 | "captures": { 368 | "1": {"name": "keyword.other.source.abl"}, 369 | "2": {"name": "variable.property.abl"} 370 | } 371 | }, 372 | { 373 | "comment": "variable", 374 | "begin": "(?i)(def(?:ine)?\\s+)(new\\s+)?(shared\\s+)?((private|protected|public)\\s+)?(var(?:iable)?)", 375 | "beginCaptures": { 376 | "1": {"name": "keyword.other.source.abl"}, 377 | "2": {"name": "keyword.other.source.abl"}, 378 | "3": {"name": "keyword.other.source.abl"}, 379 | "4": {"name": "storage.modifier.source.abl"}, 380 | "5": {"name": "storage.modifier.source.abl"}, 381 | "6": {"name": "keyword.other.source.abl"} 382 | }, 383 | "patterns": [ 384 | { "include": "#constantHTMLColors" }, 385 | { "include": "#constantNumbers" }, 386 | { "include": "#dataTypes" }, 387 | { "include": "#defineKeywords" }, 388 | { "include": "#fileField" }, 389 | { "include": "#keywordAsLike" }, 390 | { "include": "#quotedStrings" }, 391 | { "include": "#variableNames" } 392 | ], 393 | "end": "\\." 394 | }, 395 | 396 | 397 | { 398 | "match": "(?i)\\b(def(?:ine)?\\s+(new\\s+)?(shared\\s+)?(temp-table|form))\\b", 399 | "name": "storage.type.define.abl" 400 | }, 401 | 402 | { 403 | "match": "(?i)\\b(? 2 | 3 | 4 | 5 | fileTypes 6 | 7 | p 8 | i 9 | cls 10 | fct 11 | def 12 | ds 13 | 14 | name 15 | OpenEdge ABL 16 | patterns 17 | 18 | 19 | match 20 | comment: 21 | name 22 | comment.testing 23 | 24 | 25 | begin 26 | /\* 27 | comment 28 | regular comment block. todo - require space when compile, if yes then change to not highlight 29 | end 30 | \*/ 31 | name 32 | comment.block.source.abl 33 | patterns 34 | 35 | 36 | begin 37 | /\* 38 | end 39 | \*/ 40 | name 41 | comment.block.source.abl 42 | 43 | 44 | 45 | 46 | match 47 | constant: 48 | name 49 | constant.testing 50 | 51 | 52 | include 53 | #constantHTMLColors 54 | 55 | 56 | include 57 | #constantNumbers 58 | 59 | 60 | comment 61 | boolean conditions. 62 | match 63 | (?i)\s(=|eq|<|lt|>|gt|<=|le|>=|ge|<>)\s 64 | name 65 | constant.character.source.abl 66 | 67 | 68 | comment 69 | math operators. 70 | match 71 | (\+|\-|\*|/) 72 | name 73 | constant.character.math.operator.source.abl 74 | 75 | 76 | comment 77 | constants - operators - simple list. 78 | match 79 | (?i)\b(and|as|false|no(?!-)|not|of|on|or|to|true|yes)\b 80 | name 81 | constant.language.source.abl 82 | 83 | 84 | match 85 | entity: 86 | name 87 | entity.testing 88 | 89 | 90 | captures 91 | 92 | 1 93 | 94 | name 95 | entity.name.function.abl 96 | 97 | 2 98 | 99 | name 100 | storage.modifier.abl 101 | 102 | 3 103 | 104 | name 105 | storage.modifier.abl 106 | 107 | 4 108 | 109 | name 110 | entity.name.hidden.abl 111 | 112 | 113 | comment 114 | constructor/destructor method 115 | match 116 | (?i)(constructor|destructor)\s+((private|protected|public)\s+)?((static)\s+)?([a-z]+) 117 | name 118 | meta.function.source.abl 119 | 120 | 121 | captures 122 | 123 | 1 124 | 125 | name 126 | keyword.control.source.abl 127 | 128 | 2 129 | 130 | name 131 | entity.name.function.abl 132 | 133 | 3 134 | 135 | name 136 | keyword.other.source.abl 137 | 138 | 4 139 | 140 | name 141 | storage.type.datatype.abl 142 | 143 | 144 | comment 145 | function 146 | match 147 | (?i)(function)\s+([a-z0-9_-]+)\s+(returns)\s+(char(?:acter)?|datetime-tz|datetime|date|decimal|int(?:eger)?|int64|logical|longchar|memptr)(\s+)?(\(|\n) 148 | name 149 | meta.function.source.abl 150 | 151 | 152 | captures 153 | 154 | 1 155 | 156 | name 157 | entity.name.function.abl 158 | 159 | 160 | comment 161 | main block 162 | match 163 | (?i)(main(\-)?block): 164 | name 165 | meta.function.source.abl 166 | 167 | 168 | begin 169 | (?i)(method)\s+((override|private|protected|public)\s+)?((static)\s+)?([a-zA-Z0-9.]+)\s+([a-zA-Z]+) 170 | beginCaptures 171 | 172 | 1 173 | 174 | name 175 | keyword.control.source.abl 176 | 177 | 2 178 | 179 | name 180 | storage.modifier.abl 181 | 182 | 3 183 | 184 | name 185 | storage.type.datatype.abl 186 | 187 | 4 188 | 189 | name 190 | entity.name.function.abl 191 | 192 | 193 | comment 194 | method 195 | end 196 | \): 197 | patterns 198 | 199 | 200 | include 201 | #constantNumbers 202 | 203 | 204 | include 205 | #dataTypes 206 | 207 | 208 | include 209 | #defineKeywords 210 | 211 | 212 | include 213 | #fileField 214 | 215 | 216 | include 217 | #keywordAsLike 218 | 219 | 220 | include 221 | #variableNames 222 | 223 | 224 | 225 | 226 | captures 227 | 228 | 1 229 | 230 | name 231 | keyword.control.source.abl 232 | 233 | 2 234 | 235 | name 236 | entity.name.function.abl 237 | 238 | 239 | comment 240 | procedure 241 | match 242 | (?i)(procedure)\s+([a-z0-9\/_-]+)(:|\(|\n) 243 | name 244 | meta.function.source.abl 245 | 246 | 247 | match 248 | exception: 249 | name 250 | support.type.exception.testing 251 | 252 | 253 | match 254 | invalid: 255 | name 256 | invalid.testing 257 | 258 | 259 | match 260 | keyword: 261 | name 262 | keyword.testing 263 | 264 | 265 | comment 266 | Accumulate keywords 267 | match 268 | (?i)\b(accumulate|accum|averate|count|maximum|minimum|total|sub-average|sub-count|sub-maximum|sub-minimum|sub-total|lable|by)\b 269 | name 270 | keyword.other.class.source.abl 271 | 272 | 273 | comment 274 | Case keywords 275 | match 276 | (?i)\b(|case|when|otherwise)\b 277 | name 278 | keyword.other.class.source.abl 279 | 280 | 281 | captures 282 | 283 | 1 284 | 285 | name 286 | keyword.control.end.source.abl 287 | 288 | 2 289 | 290 | name 291 | keyword.control.end.source.abl 292 | 293 | 294 | comment 295 | ends keywords. 296 | match 297 | (?i)(end)(\s+(case|class|constructor|destructor|finally|function|interface|method|procedure))?\. 298 | 299 | 300 | comment 301 | Find & For keywords 302 | match 303 | (?i)\b(can-find(\((first|last|prev))?|find\s+(first|last|prev)?|for\s+(each|first|last)|by|descending|exclusive-lock|exclusive|no-lock|no-wait|of|share-lock|transaction|use-index|using|where|while)\b 304 | name 305 | keyword.other.class.source.abl 306 | 307 | 308 | comment 309 | format & frame keywords 310 | match 311 | (?i)\b(as|attr-space|auto-return|bgcolor|blank|cancel-button|centered|colon|column-label|columns|column|context-help|context-help-file|dcolor|deblank|default-buttone|disable-auto-zap|down|fgcolor|font|format|frame|help|keep-tab-order|label|like|no-attr-space|no-box|no-help|no-hide|no-labels|no-tab-stop|no-underline|no-validate|overlay|page-bottom|page-top|pfcolor|retain|row|screen-id|stream-io|scrollable|scroll|side-labels|skip|stream|three-d|top-only|to|use-dect-exps|use-text|v6frame|validate|view-as dialog-box|width|with)\b 312 | name 313 | keyword.other.frames.source.abl 314 | 315 | 316 | comment 317 | message keywords 318 | match 319 | (?i)\b(message|auto-return|buttons|color|in window|set|skip|title|update|view-as alert-box)\b 320 | name 321 | keyword.other.class.source.abl 322 | 323 | 324 | comment 325 | on block keywords 326 | match 327 | (?i)\b(on|endkey|error|quit|stop|anywhere|leave|next|no-apply|override|persistent run|retry|return|revert|undo)\b 328 | name 329 | keyword.other.class.source.abl 330 | 331 | 332 | comment 333 | output keywords 334 | match 335 | (?i)\b(output|append|binary|close|collate|convert|echo|keep-messages|landscape|map|no-convert|no-echo|no-map|num-copies|paged|page-size|portrait|printer|stream|terminal|through|to|unbuffered|value)\b 336 | name 337 | keyword.other.class.source.abl 338 | 339 | 340 | comment 341 | put keywords 342 | match 343 | (?i)\b(put|attr-space|color|column|control|cursor|format|no-attr-space|off|row|skip|screen|stream|unformatted)\b 344 | name 345 | keyword.other.class.source.abl 346 | 347 | 348 | comment 349 | Other keywords - A - B 350 | match 351 | (?i)\b(absolute|add-interval|alias|ambiguous|apply|asc|assign|at|available|begins|bell|browse|buffer)\b 352 | name 353 | keyword.other.class.source.abl 354 | 355 | 356 | comment 357 | Other keywords - C 358 | match 359 | (?i)\b(call|can-do|can-query|can-set|caps|cast|catch|class|choose|chr|clear|close|codepage-convert|color|combo-box|compare|compile|compiler|save|connect|connected|count-of|create|current-changed|current-language|current-result-row|current-value)\b 360 | name 361 | keyword.other.class.source.abl 362 | 363 | 364 | comment 365 | Other keywords - D 366 | match 367 | (?i)\b(dataservers|datetime-tz|datetime|date|daydbcodepage|dbcollation|dbname|dbparam|dbrestrictions|dbtaskid|dbtype|dbversion|decimal|delete|delimiter|dictionary|disable|disconnect|display|do|down|dynamic-function|dynamic-new)\b 368 | name 369 | keyword.other.class.source.abl 370 | 371 | 372 | comment 373 | Other keywords - E - F 374 | match 375 | (?i)\b(editing|editor|empty temp-table|enable|encode|entered|entry|etime|exp|export|extent|fill|finally|final|first-of|first|form)\b 376 | name 377 | keyword.other.class.source.abl 378 | 379 | 380 | comment 381 | Other keywords - G 382 | match 383 | (?i)\b(gateways|get|get-bits|get-byte|get-byte-order|get-bytes|get-codepages|get-collations|get-double|get-float|get-key-value|get-long|get-pointer-value|get-short|get-size|get-string|get-unsigned-short|go-pending)\b 384 | name 385 | keyword.other.class.source.abl 386 | 387 | 388 | comment 389 | Other keywords - H - I 390 | match 391 | (?i)\b(hex-encode|hide|if|then|else|image|implements|import|index|inherits|input\s+(clear|close|from|through)?|insert|integer|interface|interval|is-attr-space|is-lead-byte)\b 392 | name 393 | keyword.other.class.source.abl 394 | 395 | 396 | comment 397 | Other keywords - K - L 398 | match 399 | (?i)\b(kblabel|keycode|keyfunction|keylable|keyword|keyword-all|last|lastkey|last-of|lc|ldbname|leave|left-trim|length|library|lin-counter|list-(events|query-attrs|set-attrs|widgets)|load|load-picture|locked|log|lookup)\b 400 | name 401 | keyword.other.class.source.abl 402 | 403 | 404 | comment 405 | Other keywords - M - N 406 | match 407 | (?i)\b(matches|maximum|max|md5-digest|member|message-lines|minimum|modulo|month|new|next|next-prompt|next-value|num-aliases|num-dbs|num-entries|num-results)\b 408 | name 409 | keyword.other.class.source.abl 410 | 411 | 412 | comment 413 | Other keywords - O 414 | match 415 | (?i)\b(open query|opsys|os-(append|command|copy|create-dir|delete|drives|error|getenv|rename)|overlay)\b 416 | name 417 | keyword.other.class.source.abl 418 | 419 | 420 | comment 421 | Other keywords - P 422 | match 423 | (?i)\b(page|page-number|page-size|pause|pdbname|preselect|proc-handle|proc-status|process events|program-name|projpt-for|promsgs|propath|proversion|publsih|put cursor|put screen|put-(bits|bytes|byte|double|float|key-value|long|session|short|string|unsigned-short))\b 424 | name 425 | keyword.other.class.source.abl 426 | 427 | 428 | comment 429 | Other keywords - U 430 | match 431 | (?i)\b(use-widget-pool|using)\b 432 | name 433 | keyword.other.class.source.abl 434 | 435 | 436 | comment 437 | class keywords. 438 | match 439 | (?i)\b(super)\b 440 | name 441 | keyword.other.class.source.abl 442 | 443 | 444 | comment 445 | control keywords. 446 | match 447 | (?i)\b(repeat|return|then|transaction:?|when)\b 448 | name 449 | keyword.control.source.abl 450 | 451 | 452 | comment 453 | general keywords. 454 | match 455 | (?i)\b(object|output\s+(close|thru|through|to)|put(\sunformatted)?|replace|routine-level|substitute|substring|throw|triggers for load of|trim|undo|update|valid-handle|valid-object)\b 456 | name 457 | keyword.other.statement.source.abl 458 | 459 | 460 | comment 461 | query keywords. 462 | match 463 | (?i)\b(query|table|temp-table)\b 464 | name 465 | keyword.other.statement.source.abl 466 | 467 | 468 | comment 469 | buffer attributes 470 | match 471 | (?i):(adm-data|available|can-create|can-delete|can-read|can-write|current-changed|dbname|handle|locked|name|new|next-sibling|num-fields|primary|private-data|recid|record-length|rowid|table|table-handle|table-number|type|unique-id)\b 472 | name 473 | keyword.other.statement.source.abl 474 | 475 | 476 | comment 477 | buffer methods 478 | match 479 | (?i):(buffer-compare|buffer-copy|buffer-create|buffer-delete|buffer-field|buffer-release|empty-temp-table|find-by-rowid|index-information|raw-transfer)\b 480 | name 481 | keyword.other.statement.source.abl 482 | 483 | 484 | comment 485 | buffer field attributes 486 | match 487 | (?i):(adm-data|buffer-handle|buffer-name|buffer-value|can-read|can-write|case-sensitive|column-label|data-type|dbname|extent|format|handle|mandatory|name|position|private-data|read-only|string-value|table|type|unique-id|validate-expression|validate-message|width-chars)\b 488 | name 489 | keyword.other.statement.source.abl 490 | 491 | 492 | comment 493 | error and error-status attributes & methods 494 | match 495 | (?i)(error-status|error|no-error|num-message|type|get-message|get-number)|(:(apperror|syserror|getMessage|numMessages|returnValue))\b 496 | name 497 | keyword.other.statement.source.abl 498 | 499 | 500 | comment 501 | query attributes 502 | match 503 | (?i):(adm-data|cache|current-result-row|handle|index-information|is-open|name|num-buffers|num-results|prepare-string|private-data|query-off-end|skip-deleted-record|type)\b 504 | name 505 | keyword.other.statement.source.abl 506 | 507 | 508 | comment 509 | query methods 510 | match 511 | (?i):(add-buffer|create-result-list-entry|delete-result-list-entry|get-buffer-handle|get-current|get-first|get-last|get-next|get-prev|set-buffers|query-close|query-open|query-prepare|reposition-backward|reposition-forward|reposition-to-row|reposition-to-rowid)\b 512 | name 513 | keyword.other.statement.source.abl 514 | 515 | 516 | comment 517 | temp-table attributes & methods 518 | match 519 | (?i):(default-buffer-handle|name|prepared|primary|undo|add-fields-from|add-index-field|add-like-field|add-like-index|add-new-field|add-new-index|clear|create-like|temp-table-prepare)\b 520 | name 521 | keyword.other.statement.source.abl 522 | 523 | 524 | match 525 | punctuation: 526 | name 527 | punctuation.string.testing 528 | 529 | 530 | match 531 | storage: 532 | name 533 | storage.testing 534 | 535 | 536 | captures 537 | 538 | 1 539 | 540 | name 541 | keyword.other.source.abl 542 | 543 | 2 544 | 545 | name 546 | variable.property.abl 547 | 548 | 3 549 | 550 | name 551 | variable.property.abl 552 | 553 | 4 554 | 555 | name 556 | constant.other.source.abl 557 | 558 | 5 559 | 560 | name 561 | text.other.source.abl 562 | 563 | 6 564 | 565 | name 566 | text.other.source.abl 567 | 568 | 569 | comment 570 | buffer 571 | match 572 | (?i)(def(?:ine)?\s+buffer)\s+(b|bf)([A-Z][a-zA-Z0-9-]+)\s+(for)\s+([a-zA-Z0-9-]+) 573 | 574 | 575 | captures 576 | 577 | 1 578 | 579 | name 580 | keyword.other.source.abl 581 | 582 | 2 583 | 584 | name 585 | variable.other.synergy.abl 586 | 587 | 3 588 | 589 | name 590 | variable.other.synergy.abl 591 | 592 | 4 593 | 594 | name 595 | constant.other.source.abl 596 | 597 | 5 598 | 599 | name 600 | storage.type.source.abl 601 | 602 | 6 603 | 604 | name 605 | constant.other.source.abl 606 | 607 | 7 608 | 609 | name 610 | text.other.source.abl 611 | 612 | 613 | comment 614 | parameters - for functions and methods 615 | match 616 | (?i)(input)\s+(i|ip)([A-Z][a-zA-Z0-9]+)\s+(as\s+(char(?:acter)?|datetime-tz|datetime|date|decimal|int(?:eger)?|int64|logical|longchar|memptr)|(like)\s+([a-zA-Z0-9-]+\.[a-zA-Z0-9_-]+)) 617 | 618 | 619 | captures 620 | 621 | 1 622 | 623 | name 624 | keyword.other.source.abl 625 | 626 | 2 627 | 628 | name 629 | keyword.other.source.abl 630 | 631 | 3 632 | 633 | name 634 | keyword.other.source.abl 635 | 636 | 4 637 | 638 | name 639 | variable.property.abl 640 | 641 | 5 642 | 643 | name 644 | keyword.other.source.abl 645 | 646 | 6 647 | 648 | name 649 | storage.type.source.abl 650 | 651 | 7 652 | 653 | name 654 | keyword.other.source.abl 655 | 656 | 657 | comment 658 | parameters - for procedures 659 | match 660 | (?i)(def(?:ine)?)\s+(input|output|input-output)\s+(parameter)\s+([a-z0-9\-_]+)\s+(as)\s+([a-z\-]+)(\s*no-undo)? 661 | 662 | 663 | begin 664 | (?i)(def(?:ine)?\s+property) 665 | beginCaptures 666 | 667 | 1 668 | 669 | name 670 | keyword.other.source.abl 671 | 672 | 673 | comment 674 | property 675 | end 676 | (?i)(set)\. 677 | endCaptures 678 | 679 | 1 680 | 681 | name 682 | keyword.other.source.abl 683 | 684 | 685 | patterns 686 | 687 | 688 | match 689 | (?i)(get) 690 | name 691 | keyword.other.source.abl 692 | 693 | 694 | include 695 | #dataTypes 696 | 697 | 698 | include 699 | #defineKeywords 700 | 701 | 702 | include 703 | #fileField 704 | 705 | 706 | include 707 | #keywordAsLike 708 | 709 | 710 | include 711 | #objectStatus 712 | 713 | 714 | include 715 | #variableNames 716 | 717 | 718 | 719 | 720 | captures 721 | 722 | 1 723 | 724 | name 725 | keyword.other.source.abl 726 | 727 | 2 728 | 729 | name 730 | variable.property.abl 731 | 732 | 3 733 | 734 | name 735 | variable.property.abl 736 | 737 | 4 738 | 739 | name 740 | constant.other.source.abl 741 | 742 | 5 743 | 744 | name 745 | text.other.source.abl 746 | 747 | 748 | comment 749 | query 750 | match 751 | (?i)(def(?:ine)?\s+query)\s+((q|qy)[A-Z][a-zA-Z0-9-]+)\s+(for)\s+([a-zA-Z0-9-]+) 752 | 753 | 754 | captures 755 | 756 | 1 757 | 758 | name 759 | keyword.other.source.abl 760 | 761 | 2 762 | 763 | name 764 | variable.property.abl 765 | 766 | 767 | comment 768 | stream 769 | match 770 | (?i)(def(?:ine)?\s+stream)\s+([a-zA-Z0-9]+)\. 771 | 772 | 773 | begin 774 | (?i)(def(?:ine)?\s+)(new\s+)?(shared\s+)?((private|protected|public)\s+)?(var(?:iable)?) 775 | beginCaptures 776 | 777 | 1 778 | 779 | name 780 | keyword.other.source.abl 781 | 782 | 2 783 | 784 | name 785 | keyword.other.source.abl 786 | 787 | 3 788 | 789 | name 790 | keyword.other.source.abl 791 | 792 | 4 793 | 794 | name 795 | storage.modifier.source.abl 796 | 797 | 5 798 | 799 | name 800 | storage.modifier.source.abl 801 | 802 | 6 803 | 804 | name 805 | keyword.other.source.abl 806 | 807 | 808 | comment 809 | variable 810 | end 811 | \. 812 | patterns 813 | 814 | 815 | include 816 | #constantHTMLColors 817 | 818 | 819 | include 820 | #constantNumbers 821 | 822 | 823 | include 824 | #dataTypes 825 | 826 | 827 | include 828 | #defineKeywords 829 | 830 | 831 | include 832 | #fileField 833 | 834 | 835 | include 836 | #keywordAsLike 837 | 838 | 839 | include 840 | #quotedStrings 841 | 842 | 843 | include 844 | #variableNames 845 | 846 | 847 | 848 | 849 | match 850 | (?i)\b(def(?:ine)?\s+(new\s+)?(shared\s+)?(temp-table|form))\b 851 | name 852 | storage.type.define.abl 853 | 854 | 855 | match 856 | (?i)\b(?<!&)((?<!-)handle|dataset-handle|dataset|field|(?<!-)index|frame [a-z]+)(?!\s*\()\b 857 | name 858 | storage.type.source.abl 859 | 860 | 861 | match 862 | string: 863 | name 864 | string.testing 865 | 866 | 867 | include 868 | #quotedStrings 869 | 870 | 871 | match 872 | support: 873 | name 874 | support.testing 875 | 876 | 877 | comment 878 | includes 879 | match 880 | (?i)\{\s*([a-zA-Z0-9\-_\/\.]+\.i)\s*(.*)\s*\} 881 | name 882 | support.function.include.abl 883 | 884 | 885 | comment 886 | preprocessors 887 | match 888 | (?i)\{&[a-zA-Z0-9_\.\/\-\s]+\} 889 | name 890 | support.function.source.abl 891 | 892 | 893 | match 894 | regular text: 895 | name 896 | text 897 | 898 | 899 | include 900 | #fileField 901 | 902 | 903 | match 904 | variable: 905 | name 906 | variable.testing 907 | 908 | 909 | comment 910 | paramaters - Synergy naming conventions 911 | match 912 | (?i)\b(i|ip|o|op|io)(-|[A-Z])[a-zA-Z0-9_-]+\b 913 | name 914 | variable.other.synergy.source.abl 915 | 916 | 917 | include 918 | #variableNames 919 | 920 | 921 | captures 922 | 923 | 1 924 | 925 | name 926 | keyword.statement.source.abl 927 | 928 | 2 929 | 930 | name 931 | support.function.source.abl 932 | 933 | 934 | match 935 | (?i)\b(run) ([a-z][a-z0-9_-]*?)\b(\s*\(.*?\))? 936 | name 937 | support.function.abl 938 | 939 | 940 | repository 941 | 942 | constantHTMLColors 943 | 944 | comment 945 | html colors 946 | match 947 | #[0-9a-fA-F]{6} 948 | name 949 | constant.numeric.source.abl 950 | 951 | constantNumbers 952 | 953 | comment 954 | numbers only - not for hex codes which never show up in ABL 955 | match 956 | \b\d+\b 957 | name 958 | constant.numeric.source.abl 959 | 960 | dataTypes 961 | 962 | comment 963 | data types - ABL specific 964 | match 965 | (?i)\b(blob|char(?:acter)?|clob|datetime-tz|datetime|date|decimal|handle|int(?:eger)?|int64|logical|longchar|memptr)\b 966 | name 967 | storage.type.source.abl 968 | 969 | defineKeywords 970 | 971 | comment 972 | define statment keywords (others) 973 | match 974 | (?i)\b(format|initial|no-undo)\b 975 | name 976 | keyword.other.source.abl 977 | 978 | fileField 979 | 980 | comment 981 | file.field referencesc 982 | match 983 | (?i)\b([a-zA-Z0-9-]+\.[a-zA-Z0-9_-]+)\b 984 | name 985 | text.other.source.abl 986 | 987 | keywordAsLike 988 | 989 | comment 990 | keywords - as or like 991 | match 992 | (?i)\b(as|like)\b 993 | name 994 | constant.other.source.abl 995 | 996 | objectStatus 997 | 998 | captures 999 | 1000 | 1 1001 | 1002 | name 1003 | storage.modifier.source.abl 1004 | 1005 | 1006 | match 1007 | (?i)(private|protected|public)\s+ 1008 | 1009 | progressComment 1010 | 1011 | patterns 1012 | 1013 | 1014 | begin 1015 | /\* 1016 | end 1017 | \*/ 1018 | name 1019 | comment.block.source.abl 1020 | 1021 | 1022 | 1023 | quotedStrings 1024 | 1025 | comment 1026 | quoted strings 1027 | patterns 1028 | 1029 | 1030 | comment 1031 | Single quoted string 1032 | match 1033 | ('(?:'|.)*?') 1034 | name 1035 | string.single.source.abl 1036 | 1037 | 1038 | comment 1039 | Double quoted string 1040 | match 1041 | ("(?:"|.)*?") 1042 | name 1043 | string.double.source.abl 1044 | 1045 | 1046 | 1047 | variableNames 1048 | 1049 | comment 1050 | variable & properties - Synergy naming conventions 1051 | match 1052 | (?i)\b(h|i|lv|o|p|sv|v)(-|[A-Z])[a-zA-Z0-9_-]+\b 1053 | name 1054 | variable.other.synergy.source.abl 1055 | 1056 | 1057 | scopeName 1058 | source.abl 1059 | uuid 1060 | 3bcebd60-f6cc-404f-930a-528f32956502 1061 | 1062 | 1063 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/ABL_Comments.JSON-tmPreferences: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Comments", 3 | "scope": "source.abl", 4 | "settings": { 5 | "shellVariables": [ 6 | { 7 | "name": "TM_COMMENT_START", 8 | "value": "/* " 9 | }, 10 | { 11 | "name": "TM_COMMENT_END", 12 | "value": " */" 13 | } 14 | ] 15 | }, 16 | "uuid": "3bcebd60-f6cc-404f-930a-528f32956502" 17 | } -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/ABL_Comments.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | name 6 | Comments 7 | scope 8 | source.abl 9 | settings 10 | 11 | shellVariables 12 | 13 | 14 | name 15 | TM_COMMENT_START 16 | value 17 | /* 18 | 19 | 20 | name 21 | TM_COMMENT_END 22 | value 23 | */ 24 | 25 | 26 | 27 | uuid 28 | 3bcebd60-f6cc-404f-930a-528f32956502 29 | 30 | 31 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/AblUppercase.py: -------------------------------------------------------------------------------- 1 | import sublime 2 | import sublime_plugin 3 | 4 | 5 | class AblUppercaseCommand( sublime_plugin.TextCommand ): 6 | 7 | def run( self, edit, **kargs ): 8 | 9 | abl_settings = self.view.settings().get('abl') 10 | 11 | if abl_settings['uppercase_keywords']: 12 | # can't use `view.sel()[:]` because it gives an error `TypeError: an integer is required` 13 | selections = [ cursor for cursor in self.view.sel() ] 14 | to_uppercase = [] 15 | 16 | for sel in selections: 17 | 18 | if sel.end() > 0: 19 | if self.view.substr( sel.end() - 1 ) == '(': 20 | offset = 2 21 | else: 22 | offset = 1 23 | 24 | #prev_item = self.view.extract_scope( sel.end() - offset ) 25 | scope = self.view.scope_name( sel.end() - offset ) 26 | begin = sel.end() - offset 27 | 28 | while self.view.scope_name( begin ) == scope and begin > 0: 29 | begin -= 1 30 | 31 | prev_item = sublime.Region( begin, sel.end() ) 32 | to_uppercase.append( prev_item ) 33 | 34 | self.view.sel().clear() 35 | self.view.sel().add_all( to_uppercase ) 36 | self.view.run_command( 'upper_case' ) 37 | 38 | self.view.sel().clear() 39 | self.view.sel().add_all( selections ) 40 | 41 | self.view.run_command( 'insert', { 'characters': kargs["keystroke"] } ) 42 | 43 | 44 | class ScopeBeforeCursorEventListener( sublime_plugin.EventListener ): 45 | """ 46 | Event listener used on the key binding `scope_before_cursor` available on the class's 47 | `UpperCasePreviousItemAndInsertSpaceCommand` documentation. 48 | """ 49 | 50 | def on_query_context( self, view, key, operator, operand, match_all ): 51 | 52 | if key != 'scope_before_cursor': 53 | return None 54 | 55 | if operator not in ( sublime.OP_EQUAL, sublime.OP_NOT_EQUAL ): 56 | return None 57 | 58 | match = False 59 | 60 | for sel in view.sel(): 61 | #print( max(0, sel.end() - 1) ) 62 | 63 | if view.substr(sel.end() - 1) == '(': 64 | offset = 2 65 | else: 66 | offset = 1 67 | 68 | for op in operand: 69 | match = view.match_selector( max(0, sel.end() - offset ), op ) 70 | #print( 'On 1º match: ', match ) 71 | 72 | if match: 73 | break 74 | 75 | if operator == sublime.OP_NOT_EQUAL: 76 | match = not match 77 | 78 | if match != match_all: 79 | break 80 | 81 | #print( 'match: ', match ) 82 | return match -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/Cobalt.tmTheme: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | comment 6 | Created by Jacob Rus. Based on ‘Slate’ by Wilson Miner 7 | author 8 | Jacob Rus 9 | name 10 | Cobalt 11 | settings 12 | 13 | 14 | settings 15 | 16 | background 17 | #002240 18 | caret 19 | #FFFFFF 20 | foreground 21 | #FFFFFF 22 | invisibles 23 | #FFFFFF26 24 | lineHighlight 25 | #00000059 26 | selection 27 | #B36539BF 28 | 29 | 30 | 31 | name 32 | Punctuation 33 | scope 34 | punctuation - (punctuation.definition.string || punctuation.definition.comment) 35 | settings 36 | 37 | fontStyle 38 | 39 | foreground 40 | #E1EFFF 41 | 42 | 43 | 44 | name 45 | Constant 46 | scope 47 | constant 48 | settings 49 | 50 | fontStyle 51 | 52 | foreground 53 | #FF628C 54 | 55 | 56 | 57 | name 58 | Entity 59 | scope 60 | entity 61 | settings 62 | 63 | fontStyle 64 | 65 | foreground 66 | #FFDD00 67 | 68 | 69 | 70 | name 71 | Keyword 72 | scope 73 | keyword 74 | settings 75 | 76 | fontStyle 77 | 78 | foreground 79 | #FF9D00 80 | 81 | 82 | 83 | name 84 | Storage 85 | scope 86 | storage 87 | settings 88 | 89 | fontStyle 90 | 91 | foreground 92 | #FFEE80 93 | 94 | 95 | 96 | name 97 | String 98 | scope 99 | string -string.unquoted.old-plist -string.unquoted.heredoc, string.unquoted.heredoc string 100 | settings 101 | 102 | fontStyle 103 | 104 | foreground 105 | #3AD900 106 | 107 | 108 | 109 | name 110 | Comment 111 | scope 112 | comment 113 | settings 114 | 115 | fontStyle 116 | italic 117 | foreground 118 | #0088FF 119 | 120 | 121 | 122 | name 123 | Support 124 | scope 125 | support 126 | settings 127 | 128 | fontStyle 129 | 130 | foreground 131 | #80FFBB 132 | 133 | 134 | 135 | name 136 | Variable 137 | scope 138 | variable 139 | settings 140 | 141 | fontStyle 142 | 143 | foreground 144 | #CCCCCC 145 | 146 | 147 | 148 | name 149 | Lang Variable 150 | scope 151 | variable.language 152 | settings 153 | 154 | fontStyle 155 | 156 | foreground 157 | #FF80E1 158 | 159 | 160 | 161 | name 162 | Function Call 163 | scope 164 | meta.function-call 165 | settings 166 | 167 | foreground 168 | #FFEE80 169 | 170 | 171 | 172 | name 173 | Invalid 174 | scope 175 | invalid 176 | settings 177 | 178 | background 179 | #800F00 180 | foreground 181 | #F8F8F8 182 | 183 | 184 | 185 | name 186 | Embedded Source 187 | scope 188 | text.other, text source, string.unquoted.heredoc, source source 189 | settings 190 | 191 | background 192 | #002240 193 | fontStyle 194 | bold 195 | foreground 196 | #e0e0e0 197 | 198 | 199 | 200 | name 201 | Entity inherited-class 202 | scope 203 | entity.other.inherited-class 204 | settings 205 | 206 | fontStyle 207 | italic 208 | foreground 209 | #80FCFF 210 | 211 | 212 | 213 | name 214 | String embedded-source 215 | scope 216 | string.quoted source 217 | settings 218 | 219 | fontStyle 220 | 221 | foreground 222 | #9EFF80 223 | 224 | 225 | 226 | name 227 | String constant 228 | scope 229 | string constant 230 | settings 231 | 232 | foreground 233 | #80FF82 234 | 235 | 236 | 237 | name 238 | String.regexp 239 | scope 240 | string.regexp 241 | settings 242 | 243 | foreground 244 | #80FFC2 245 | 246 | 247 | 248 | name 249 | String variable 250 | scope 251 | string variable 252 | settings 253 | 254 | foreground 255 | #EDEF7D 256 | 257 | 258 | 259 | name 260 | Support.function 261 | scope 262 | support.function 263 | settings 264 | 265 | fontStyle 266 | 267 | foreground 268 | #FFB054 269 | 270 | 271 | 272 | name 273 | Support.constant 274 | scope 275 | support.constant 276 | settings 277 | 278 | fontStyle 279 | 280 | foreground 281 | #EB939A 282 | 283 | 284 | 285 | name 286 | Exception 287 | scope 288 | support.type.exception 289 | settings 290 | 291 | foreground 292 | #FF1E00 293 | 294 | 295 | 296 | name 297 | C/C++ Preprocessor Line 298 | scope 299 | meta.preprocessor.c 300 | settings 301 | 302 | foreground 303 | #8996A8 304 | 305 | 306 | 307 | name 308 | C/C++ Preprocessor Directive 309 | scope 310 | meta.preprocessor.c keyword 311 | settings 312 | 313 | foreground 314 | #AFC4DB 315 | 316 | 317 | 318 | name 319 | Doctype/XML Processing 320 | scope 321 | meta.sgml.html meta.doctype, meta.sgml.html meta.doctype entity, meta.sgml.html meta.doctype string, meta.xml-processing, meta.xml-processing entity, meta.xml-processing string 322 | settings 323 | 324 | foreground 325 | #73817D 326 | 327 | 328 | 329 | name 330 | Meta.tag.A 331 | scope 332 | meta.tag, meta.tag entity 333 | settings 334 | 335 | foreground 336 | #9EFFFF 337 | 338 | 339 | 340 | name 341 | css tag-name 342 | scope 343 | meta.selector.css entity.name.tag 344 | settings 345 | 346 | foreground 347 | #9EFFFF 348 | 349 | 350 | 351 | name 352 | css#id 353 | scope 354 | meta.selector.css entity.other.attribute-name.id 355 | settings 356 | 357 | foreground 358 | #FFB454 359 | 360 | 361 | 362 | name 363 | css.class 364 | scope 365 | meta.selector.css entity.other.attribute-name.class 366 | settings 367 | 368 | foreground 369 | #5FE461 370 | 371 | 372 | 373 | name 374 | css property-name: 375 | scope 376 | support.type.property-name.css 377 | settings 378 | 379 | foreground 380 | #9DF39F 381 | 382 | 383 | 384 | name 385 | css property-value; 386 | scope 387 | meta.property-group support.constant.property-value.css, meta.property-value support.constant.property-value.css 388 | settings 389 | 390 | foreground 391 | #F6F080 392 | 393 | 394 | 395 | name 396 | css @at-rule 397 | scope 398 | meta.preprocessor.at-rule keyword.control.at-rule 399 | settings 400 | 401 | foreground 402 | #F6AA11 403 | 404 | 405 | 406 | name 407 | css additional-constants 408 | scope 409 | meta.property-value support.constant.named-color.css, meta.property-value constant 410 | settings 411 | 412 | foreground 413 | #EDF080 414 | 415 | 416 | 417 | name 418 | css constructor.argument 419 | scope 420 | meta.constructor.argument.css 421 | settings 422 | 423 | foreground 424 | #EB939A 425 | 426 | 427 | 428 | name 429 | diff.header 430 | scope 431 | meta.diff, meta.diff.header 432 | settings 433 | 434 | background 435 | #000E1A 436 | fontStyle 437 | 438 | foreground 439 | #F8F8F8 440 | 441 | 442 | 443 | name 444 | diff.deleted 445 | scope 446 | markup.deleted 447 | settings 448 | 449 | background 450 | #4C0900 451 | foreground 452 | #F8F8F8 453 | 454 | 455 | 456 | name 457 | diff.changed 458 | scope 459 | markup.changed 460 | settings 461 | 462 | background 463 | #806F00 464 | foreground 465 | #F8F8F8 466 | 467 | 468 | 469 | name 470 | diff.inserted 471 | scope 472 | markup.inserted 473 | settings 474 | 475 | background 476 | #154F00 477 | foreground 478 | #F8F8F8 479 | 480 | 481 | 482 | name 483 | Raw Markup 484 | scope 485 | markup.raw 486 | settings 487 | 488 | background 489 | #8FDDF630 490 | 491 | 492 | 493 | name 494 | Block Quote 495 | scope 496 | markup.quote 497 | settings 498 | 499 | background 500 | #004480 501 | 502 | 503 | 504 | name 505 | List 506 | scope 507 | markup.list 508 | settings 509 | 510 | background 511 | #130D26 512 | 513 | 514 | 515 | name 516 | Bold Markup 517 | scope 518 | markup.bold 519 | settings 520 | 521 | fontStyle 522 | bold 523 | foreground 524 | #C1AFFF 525 | 526 | 527 | 528 | name 529 | Italic Markup 530 | scope 531 | markup.italic 532 | settings 533 | 534 | fontStyle 535 | italic 536 | foreground 537 | #B8FFD9 538 | 539 | 540 | 541 | name 542 | Heading Markup 543 | scope 544 | markup.heading 545 | settings 546 | 547 | background 548 | #001221 549 | fontStyle 550 | bold 551 | foreground 552 | #C8E4FD 553 | 554 | 555 | 556 | uuid 557 | 06CD1FB2-A00A-4F8C-97B2-60E131980454 558 | 559 | 560 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/Default (Linux).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": [" "], "command": "abl_uppercase", 3 | "context": 4 | [ 5 | { "key": "selector", "operator": "equal", "operand": "source.abl", "match_all": true }, 6 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, 7 | { "key": "scope_before_cursor", "operator": "equal", "operand": ["keyword", "storage", "constant"], "match_all": true }, 8 | ], "args": {"keystroke": " " } 9 | }, 10 | { "keys": ["."], "command": "abl_uppercase", 11 | "context": 12 | [ 13 | { "key": "selector", "operator": "equal", "operand": "source.abl", "match_all": true }, 14 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, 15 | { "key": "scope_before_cursor", "operator": "equal", "operand": ["keyword", "storage", "constant"], "match_all": true }, 16 | ], "args": {"keystroke": "." } 17 | }, 18 | { "keys": [":"], "command": "abl_uppercase", 19 | "context": 20 | [ 21 | { "key": "selector", "operator": "equal", "operand": "source.abl", "match_all": true }, 22 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, 23 | { "key": "scope_before_cursor", "operator": "equal", "operand": ["keyword", "storage", "constant"], "match_all": true }, 24 | ], "args": {"keystroke": ":" } 25 | }, 26 | ] -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/Default (Windows).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | { "keys": [" "], "command": "abl_uppercase", 3 | "context": 4 | [ 5 | { "key": "selector", "operator": "equal", "operand": "source.abl", "match_all": true }, 6 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, 7 | { "key": "scope_before_cursor", "operator": "equal", "operand": ["keyword", "storage", "constant"], "match_all": true }, 8 | ], "args": {"keystroke": " " } 9 | }, 10 | { "keys": ["."], "command": "abl_uppercase", 11 | "context": 12 | [ 13 | { "key": "selector", "operator": "equal", "operand": "source.abl", "match_all": true }, 14 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, 15 | { "key": "scope_before_cursor", "operator": "equal", "operand": ["keyword", "storage", "constant"], "match_all": true }, 16 | ], "args": {"keystroke": "." } 17 | }, 18 | { "keys": [":"], "command": "abl_uppercase", 19 | "context": 20 | [ 21 | { "key": "selector", "operator": "equal", "operand": "source.abl", "match_all": true }, 22 | { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, 23 | { "key": "scope_before_cursor", "operator": "equal", "operand": ["keyword", "storage", "constant"], "match_all": true }, 24 | ], "args": {"keystroke": ":" } 25 | }, 26 | ] -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/Espresso Libre.tmTheme: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | author 6 | Chris Thomas 7 | name 8 | Espresso Libre 9 | settings 10 | 11 | 12 | settings 13 | 14 | background 15 | #2A211C 16 | caret 17 | #889AFF 18 | foreground 19 | #BDAE9D 20 | invisibles 21 | #BFBFBF 22 | lineHighlight 23 | #3A312C 24 | selection 25 | #C3DCFF 26 | 27 | 28 | 29 | name 30 | Comment 31 | scope 32 | comment 33 | settings 34 | 35 | fontStyle 36 | italic 37 | foreground 38 | #0066FF 39 | 40 | 41 | 42 | name 43 | Keyword 44 | scope 45 | keyword 46 | settings 47 | 48 | fontStyle 49 | bold 50 | foreground 51 | #43A8ED 52 | 53 | 54 | 55 | name 56 | Number 57 | scope 58 | constant.numeric 59 | settings 60 | 61 | fontStyle 62 | bold 63 | foreground 64 | #C5656B 65 | 66 | 67 | 68 | name 69 | User-defined constant 70 | scope 71 | constant 72 | settings 73 | 74 | fontStyle 75 | bold 76 | foreground 77 | #C5656B 78 | 79 | 80 | 81 | name 82 | Built-in constant 83 | scope 84 | constant.language 85 | settings 86 | 87 | fontStyle 88 | bold 89 | foreground 90 | #585CF6 91 | 92 | 93 | 94 | name 95 | Variable 96 | scope 97 | variable.language, variable.other 98 | settings 99 | 100 | fontStyle 101 | 102 | foreground 103 | #318495 104 | 105 | 106 | 107 | name 108 | String 109 | scope 110 | string 111 | settings 112 | 113 | fontStyle 114 | 115 | foreground 116 | #049B0A 117 | 118 | 119 | 120 | name 121 | String interpolation 122 | scope 123 | constant.character.escape, string source 124 | settings 125 | 126 | fontStyle 127 | 128 | foreground 129 | #2FE420 130 | 131 | 132 | 133 | name 134 | Preprocessor line 135 | scope 136 | meta.preprocessor 137 | settings 138 | 139 | fontStyle 140 | 141 | foreground 142 | #1A921C 143 | 144 | 145 | 146 | name 147 | Preprocessor directive 148 | scope 149 | keyword.control.import 150 | settings 151 | 152 | fontStyle 153 | bold 154 | foreground 155 | #9AFF87 156 | 157 | 158 | 159 | name 160 | Function name 161 | scope 162 | entity.name.function, keyword.other.name-of-parameter.objc 163 | settings 164 | 165 | fontStyle 166 | bold 167 | foreground 168 | #FF9358 169 | 170 | 171 | 172 | name 173 | Type name 174 | scope 175 | entity.name.type 176 | settings 177 | 178 | fontStyle 179 | underline 180 | 181 | 182 | 183 | name 184 | Inherited class name 185 | scope 186 | entity.other.inherited-class 187 | settings 188 | 189 | fontStyle 190 | italic 191 | 192 | 193 | 194 | name 195 | Function parameter 196 | scope 197 | variable.parameter 198 | settings 199 | 200 | fontStyle 201 | italic 202 | 203 | 204 | 205 | name 206 | storage 207 | scope 208 | storage 209 | settings 210 | 211 | fontStyle 212 | bold 213 | foreground 214 | #8B8E9C 215 | 216 | 217 | 218 | name 219 | Function argument and result types 220 | scope 221 | storage.type.method 222 | settings 223 | 224 | fontStyle 225 | 226 | foreground 227 | #8B8E9C 228 | 229 | 230 | 231 | name 232 | Section 233 | scope 234 | meta.section entity.name.section, declaration.section entity.name.section 235 | settings 236 | 237 | fontStyle 238 | italic 239 | 240 | 241 | 242 | name 243 | Library function 244 | scope 245 | support.function 246 | settings 247 | 248 | fontStyle 249 | bold 250 | foreground 251 | #7290D9 252 | 253 | 254 | 255 | name 256 | Library object 257 | scope 258 | support.class, support.type 259 | settings 260 | 261 | fontStyle 262 | bold 263 | foreground 264 | #6D79DE 265 | 266 | 267 | 268 | name 269 | Library constant 270 | scope 271 | support.constant 272 | settings 273 | 274 | fontStyle 275 | bold 276 | foreground 277 | #00AF0E 278 | 279 | 280 | 281 | name 282 | Library variable 283 | scope 284 | support.variable 285 | settings 286 | 287 | fontStyle 288 | bold 289 | foreground 290 | #2F5FE0 291 | 292 | 293 | 294 | name 295 | JS: Operator 296 | scope 297 | keyword.operator.js 298 | settings 299 | 300 | foreground 301 | #687687 302 | 303 | 304 | 305 | name 306 | Invalid 307 | scope 308 | invalid 309 | settings 310 | 311 | background 312 | #990000 313 | foreground 314 | #FFFFFF 315 | 316 | 317 | 318 | name 319 | Invalid trailing whitespace 320 | scope 321 | invalid.deprecated.trailing-whitespace 322 | settings 323 | 324 | background 325 | #FFD0D0 326 | 327 | 328 | 329 | name 330 | Embedded source 331 | scope 332 | text.other, text source, string.unquoted 333 | settings 334 | 335 | fontStyle 336 | bold 337 | foreground 338 | #e0e0e0 339 | 340 | 341 | 342 | name 343 | Markup XML declaration 344 | scope 345 | meta.tag.preprocessor.xml 346 | settings 347 | 348 | fontStyle 349 | 350 | foreground 351 | #8F7E65 352 | 353 | 354 | 355 | name 356 | Markup DOCTYPE 357 | scope 358 | meta.tag.sgml.doctype 359 | settings 360 | 361 | fontStyle 362 | 363 | foreground 364 | #888888 365 | 366 | 367 | 368 | name 369 | Markup DTD 370 | scope 371 | string.quoted.docinfo.doctype.DTD 372 | settings 373 | 374 | fontStyle 375 | italic 376 | 377 | 378 | 379 | name 380 | Markup tag 381 | scope 382 | meta.tag, declaration.tag 383 | settings 384 | 385 | fontStyle 386 | 387 | foreground 388 | #43A8ED 389 | 390 | 391 | 392 | name 393 | Markup name of tag 394 | scope 395 | entity.name.tag 396 | settings 397 | 398 | fontStyle 399 | bold 400 | 401 | 402 | 403 | name 404 | Markup tag attribute 405 | scope 406 | entity.other.attribute-name 407 | settings 408 | 409 | fontStyle 410 | italic 411 | 412 | 413 | 414 | uuid 415 | 6B90703E-4E4B-43C8-9D32-921BEDF6D725 416 | 417 | 418 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/abl.p: -------------------------------------------------------------------------------- 1 | USING Progress.Json.ObjectModel.ObjectModelParser. 2 | USING Progress.Json.ObjectModel.JsonObject. 3 | USING Progress.Json.ObjectModel.JsonArray. 4 | 5 | DEFINE VARIABLE oABLSettingsParser AS ObjectModelParser NO-UNDO. 6 | DEFINE VARIABLE oABLSettings AS JsonObject NO-UNDO. 7 | DEFINE VARIABLE oHooks AS JsonObject NO-UNDO. 8 | DEFINE VARIABLE oPropath AS JsonArray NO-UNDO. 9 | DEFINE VARIABLE oDBs AS JsonArray NO-UNDO. 10 | DEFINE VARIABLE iDbs AS INTEGER NO-UNDO. 11 | DEFINE VARIABLE iPropath AS INTEGER NO-UNDO. 12 | DEFINE VARIABLE cSettingsData AS LONGCHAR NO-UNDO. 13 | DEFINE VARIABLE cPropath AS CHARACTER NO-UNDO. 14 | DEFINE VARIABLE cAction AS CHARACTER NO-UNDO. 15 | DEFINE VARIABLE lCompiles AS LOGICAL NO-UNDO. 16 | 17 | FIX-CODEPAGE(cSettingsData) = "UTF-8". 18 | COPY-LOB FROM FILE SESSION:PARAMETER To cSettingsData. 19 | 20 | oABLSettingsParser = NEW ObjectModelParser(). 21 | oABLSettings = CAST(oABLSettingsParser:Parse(cSettingsData), JsonObject). 22 | 23 | cAction = oABLSettings:getCharacter("action":U). 24 | 25 | /* If we had db's lets cnnect them */ 26 | IF oABLSettings:has("db":U) 27 | THEN 28 | DO: 29 | ASSIGN 30 | oDBs = oABLSettings:getJsonArray("db":U). 31 | 32 | DO iDbs = 1 TO oDBs:Length: 33 | CONNECT VALUE(oDBs:getCharacter(iDbs)). 34 | END. 35 | END. 36 | 37 | /* If we had a propath lets set it */ 38 | IF oABLSettings:has("propath":U) 39 | THEN 40 | DO: 41 | ASSIGN 42 | cPropath = "":U 43 | oPropath = oABLSettings:getJsonArray("propath":U). 44 | 45 | DO iPropath = 1 TO oPropath:Length: 46 | cPropath = cPropath + (IF iPropath = 1 THEN "":U ELSE ",":U) + oPropath:getCharacter(iPropath). 47 | END. 48 | 49 | PROPATH = cPropath. 50 | END. 51 | 52 | /* Fire off any hooks */ 53 | IF oABLSettings:has("hooks":U) 54 | THEN 55 | DO: 56 | oHooks = oABLSettings:getJsonObject("hooks":U). 57 | 58 | IF oHooks:has("pre":U) 59 | THEN 60 | RUN VALUE(oHooks:getCharacter("pre":U)) NO-ERROR. 61 | 62 | END. 63 | 64 | CASE cAction: 65 | 66 | WHEN "check_syntax":U OR 67 | WHEN "compile":U 68 | THEN 69 | RUN abl_compile (INPUT (cAction = "compile":U), OUTPUT lCompiles). 70 | 71 | WHEN "run-batch":U OR 72 | WHEN "run-gui":U 73 | THEN 74 | DO: 75 | RUN abl_compile (INPUT TRUE, OUTPUT lCompiles). 76 | 77 | IF lCompiles 78 | THEN 79 | RUN abl_run. 80 | END. 81 | END CASE. 82 | 83 | QUIT. 84 | 85 | PROCEDURE abl_compile: 86 | DEFINE INPUT PARAMETER iplSave AS LOGICAL NO-UNDO. 87 | DEFINE OUTPUT PARAMETER oplErrors AS LOGICAL NO-UNDO INITIAL TRUE. 88 | 89 | DEFINE VARIABLE cFileName AS CHARACTER NO-UNDO. 90 | DEFINE VARIABLE cXrefXml AS CHARACTER NO-UNDO. 91 | DEFINE VARIABLE cMessage AS CHARACTER NO-UNDO. 92 | DEFINE VARIABLE iMessage AS INTEGER NO-UNDO. 93 | 94 | cFileName = oABLSettings:getCharacter("filename":U). 95 | 96 | IF iplSave 97 | THEN 98 | COMPILE VALUE(cFileName) SAVE NO-ERROR. 99 | ELSE 100 | DO: 101 | cXrefXml = cFileName + ".xref". 102 | 103 | COMPILE VALUE(cFileName) XREF-XML VALUE(cXrefXml) NO-ERROR. 104 | END. 105 | 106 | IF COMPILER:NUM-MESSAGES > 0 THEN DO: 107 | 108 | ASSIGN 109 | cMessage = "" 110 | oplErrors = FALSE. 111 | 112 | DO iMessage = 1 TO COMPILER:NUM-MESSAGES: 113 | 114 | ASSIGN cMessage = 115 | SUBSTITUTE( "&1:&2:&3 &4", 116 | COMPILER:GET-FILE-NAME ( iMessage ), 117 | COMPILER:GET-ROW ( iMessage ), 118 | COMPILER:GET-COLUMN ( iMessage ), 119 | COMPILER:GET-MESSAGE ( iMessage ) 120 | ) 121 | . 122 | 123 | IF iMessage < COMPILER:NUM-MESSAGES 124 | THEN 125 | PUT UNFORMATTED cMessage SKIP. 126 | ELSE 127 | PUT UNFORMATTED cMessage. 128 | 129 | END. 130 | END. 131 | 132 | FINALLY: 133 | IF cXrefXml <> ? AND cXrefXml <> "":U 134 | THEN 135 | OS-DELETE VALUE(cXrefXml). 136 | END FINALLY. 137 | END PROCEDURE. 138 | 139 | PROCEDURE abl_run: 140 | DEFINE VARIABLE cFileName AS CHARACTER NO-UNDO. 141 | DEFINE VARIABLE cMessage AS CHARACTER NO-UNDO. 142 | DEFINE VARIABLE iMessage AS INTEGER NO-UNDO. 143 | 144 | cFileName = oABLSettings:getCharacter("filename":U). 145 | 146 | RUN VALUE(cFileName). 147 | END. 148 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/abl.py: -------------------------------------------------------------------------------- 1 | import sublime 2 | import sublime_plugin 3 | 4 | import subprocess 5 | import threading 6 | import os 7 | 8 | import tempfile 9 | import json 10 | import uuid 11 | 12 | class AblCommand(sublime_plugin.WindowCommand): 13 | 14 | encoding = 'utf-8' 15 | killed = False 16 | proc = None 17 | panel = None 18 | panel_lock = threading.Lock() 19 | 20 | def is_enabled(self, lint=False, integration=False, kill=False): 21 | # The Cancel build option should only be available 22 | # when the process is still running 23 | if kill: 24 | return self.proc is not None and self.proc.poll() is None 25 | return True 26 | 27 | def run(self, action="check_syntax", kill=False): 28 | if kill: 29 | if self.proc: 30 | self.killed = True 31 | self.proc.terminate() 32 | return 33 | 34 | view = self.window.active_view() 35 | vars = self.window.extract_variables() 36 | 37 | view_settings = view.settings() 38 | working_dir = vars['file_path'] 39 | project_dir, project_file = os.path.split(self.window.project_file_name()) 40 | 41 | if action != 'run-gui': 42 | with self.panel_lock: 43 | # Creating the panel implicitly clears any previous contents 44 | self.panel = self.window.create_output_panel('exec') 45 | 46 | settings = self.panel.settings() 47 | settings.set( 48 | 'result_file_regex', 49 | r'(?:^(.+?):([0-9]+):([0-9]+)\s(.+)$)*' 50 | ) 51 | settings.set('result_base_dir', working_dir) 52 | 53 | self.window.run_command('show_panel', {'panel': 'output.exec'}) 54 | 55 | if self.proc is not None: 56 | self.proc.terminate() 57 | self.proc = None 58 | 59 | abl_p = os.path.join(sublime.cache_path(), 'OpenEdge ABL', 'abl.p') 60 | if not os.path.exists(abl_p): 61 | with open(abl_p, 'w') as outfile: 62 | outfile.write(sublime.load_resource('Packages/OpenEdge ABL/abl.p')) 63 | 64 | abl_settings = view_settings.get('abl'); 65 | 66 | # Resolve relative paths to project 67 | propath = abl_settings['propath'] 68 | for i, path in enumerate(propath): 69 | if not os.path.isabs(path): 70 | abl_settings['propath'][i] = os.path.join(project_dir, path) 71 | 72 | if not os.path.isabs(abl_settings['pf']): 73 | abl_settings['pf'] = os.path.join(project_dir, abl_settings['pf']) 74 | 75 | abl_settings['action'] = action 76 | 77 | if action == 'check_syntax' or action == 'compile' or action == 'run-batch' or action == 'run-gui': 78 | abl_settings['filename'] = os.path.join(vars['file_path'], vars['file_name']) 79 | 80 | abl_settings_file = os.path.join(tempfile.gettempdir(), str(uuid.uuid4()) + '.json') 81 | with open(abl_settings_file, 'w') as outfile: 82 | json.dump(abl_settings, outfile) 83 | 84 | args = [] 85 | if action == 'run-gui': 86 | if (os.name != "posix"): 87 | if os.path.exists(os.path.join(abl_settings['dlc'], 'bin', 'prowin.exe')): 88 | _progres = os.path.join(abl_settings['dlc'], 'bin', 'prowin.exe') 89 | else: 90 | _progres = os.path.join(abl_settings['dlc'], 'bin', 'prowin32.exe') 91 | else: 92 | self.queue_write('\n[GUI not supported in unix]') 93 | return 94 | 95 | args.append(_progres) 96 | 97 | else: 98 | _progres = os.path.join(abl_settings['dlc'], 'bin', '_progres') 99 | if (os.name != "posix"): 100 | _progres += ".exe" # Does windows work without this? Who knows 101 | 102 | args.append(_progres) 103 | args.append('-1') 104 | args.append('-b') 105 | 106 | 107 | 108 | # Run the entry point 109 | args.append('-p') 110 | args.append(abl_p) 111 | 112 | # Set the PF file 113 | pf_file = abl_settings['pf'] 114 | args.append('-pf') 115 | if os.path.isabs(pf_file): 116 | args.append(pf_file) 117 | else: 118 | args.append(os.path.join(project_dir, pf_file)) 119 | 120 | # Set the PARAM 121 | args.append('-param') 122 | args.append(abl_settings_file) 123 | 124 | abl_env = os.environ.copy() 125 | abl_env["DLC"] = abl_settings['dlc'] 126 | abl_env["PROMSGS"] = os.path.join(abl_settings['dlc'], 'promsgs') 127 | 128 | if (os.name == "posix"): 129 | abl_env["TERM"] = 'xterm' 130 | 131 | if action == 'run-gui': 132 | self.proc = subprocess.Popen( 133 | args, 134 | env=abl_env, 135 | cwd=working_dir 136 | ) 137 | 138 | else: 139 | self.proc = subprocess.Popen( 140 | args, 141 | env=abl_env, 142 | stdout=subprocess.PIPE, 143 | stderr=subprocess.STDOUT, 144 | cwd=working_dir 145 | ) 146 | self.killed = False 147 | 148 | thread = threading.Thread( 149 | target=self.read_handle, 150 | args=(self.proc.stdout,) 151 | ) 152 | thread.start() 153 | thread.join() 154 | # Removing this breaks the gui run, hopefully windows cleans up its temp folders? 155 | if os.path.exists(abl_settings_file): 156 | os.remove(abl_settings_file) 157 | 158 | def finished(self): 159 | stylesheet = ''' 160 | 184 | ''' 185 | 186 | errs = self.panel.find_all_results_with_text() 187 | view = self.window.active_view() 188 | view.erase_phantoms ("abl") 189 | 190 | if len(errs) > 0 and errs[0][3] != '': 191 | pt = view.text_point(errs[0][1] - 1, errs[0][2] - 1) 192 | 193 | view.add_phantom ("abl", sublime.Region(pt, view.line(pt).b), 194 | '' + stylesheet + 195 | '
' + 196 | '' + errs[0][3] + '' + 197 | '' + chr(0x00D7) + '
' + 198 | '' 199 | , sublime.LAYOUT_BLOCK 200 | , on_navigate=self.on_phantom_navigate) 201 | 202 | def on_phantom_navigate(self, url): 203 | view = self.window.active_view() 204 | view.erase_phantoms ("abl") 205 | 206 | def read_handle(self, handle): 207 | chunk_size = 2 ** 13 208 | out = b'' 209 | while True: 210 | try: 211 | data = os.read(handle.fileno(), chunk_size) 212 | # If exactly the requested number of bytes was 213 | # read, there may be more data, and the current 214 | # data may contain part of a multibyte char 215 | out += data 216 | if len(data) == chunk_size: 217 | continue 218 | if data == b'' and out == b'': 219 | raise IOError('EOF') 220 | # We pass out to a function to ensure the 221 | # timeout gets the value of out right now, 222 | # rather than a future (mutated) version 223 | self.queue_write(out.decode(self.encoding)) 224 | if data == b'': 225 | raise IOError('EOF') 226 | out = b'' 227 | except (UnicodeDecodeError) as e: 228 | msg = 'Error decoding output using %s - %s' 229 | self.queue_write(msg % (self.encoding, str(e))) 230 | break 231 | except (IOError): 232 | if self.killed: 233 | msg = 'Cancelled' 234 | else: 235 | msg = 'Finished' 236 | sublime.set_timeout(self.finished, 1) 237 | self.queue_write('\n[%s]' % msg) 238 | break 239 | 240 | def queue_write(self, text): 241 | sublime.set_timeout(lambda: self.do_write(text), 1) 242 | 243 | def do_write(self, text): 244 | with self.panel_lock: 245 | self.panel.run_command('append', {'characters': text, 'force': True, 'scroll_to_end': True}) 246 | 247 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/comment.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | pc 7 | // 8 | 9 | 10 | 11 | Insère un commentaire 12 | 13 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/debug.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | debugMessage 8 | mess 9 | 10 | 11 | 12 | Insère un message 13 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defineparam.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defpar 7 | dpar 8 | 9 | 10 | 11 | Insère un paramètre 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defpar-Int64.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defpar int64 7 | dp64 8 | 9 | 10 | 11 | Insère un paramètre de type INT64 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defpar-character.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defpar char 7 | dpch 8 | 9 | 10 | 11 | Insère un paramètre de type CHARACTER 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defpar-date.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defpar date 7 | dpdt 8 | 9 | 10 | 11 | Insère un paramètre de type DATE 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defpar-decimal.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defpar dec 7 | dpdc 8 | 9 | 10 | 11 | Insère un paramètre de type DECIMAL 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defpar-handle.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defpar handle 7 | dphd 8 | 9 | 10 | 11 | Insère un paramètre de type HANDLE 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defpar-integer.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defpar int 7 | dpin 8 | 9 | 10 | 11 | Insère un paramètre de type INTEGER 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defpar-logical.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defpar log 7 | dplg 8 | 9 | 10 | 11 | Insère un paramètre de type LOGICAL 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defpar-longchar.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defpar longchar 7 | dplc 8 | 9 | 10 | 11 | Insère un paramètre de type LONGCHAR 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defvar-Int64.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defvar int64 7 | dv64 8 | 9 | 10 | 11 | Insère une variable de type INT64 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defvar-character.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defvar char 7 | dvch 8 | 9 | 10 | 11 | Insère une variable de type CHARACTER 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defvar-date.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defvar date 7 | dvdt 8 | 9 | 10 | 11 | Insère une variable de type DATE 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defvar-decimal.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defvar dec 7 | dvdc 8 | 9 | 10 | 11 | Insère une variable de type DECIMAL 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defvar-handle.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defvar handle 7 | dvhd 8 | 9 | 10 | Insère une variable de type HANDLE 11 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defvar-integer.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defvar int 7 | dvin 8 | 9 | 10 | 11 | Insère une variable de type INTEGER 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defvar-logical.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defvar log 7 | dvlg 8 | 9 | 10 | 11 | Insère une variable de type LOGICAL 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/defvar-longchar.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | defvar longchar 7 | dvlc 8 | 9 | 10 | 11 | Insère une variable de type LONGCHAR 12 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/function forward.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | function forward 7 | 8 | 9 | Insère une entête de fonction 10 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/function.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | function 11 | func 12 | 13 | 14 | 15 | Insère une FUNCTION vide 16 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/header.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 31 | 32 | header 33 | 34 | source.abl 35 | 36 | Insère une entête de fichier 37 | 38 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/input.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | input 7 | 8 | 9 | 10 | Insère un paramètre de fonction 11 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/procedure.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | procedure 10 | proc 11 | 12 | 13 | 14 | Insère une PROCEDURE vide 15 | 16 | -------------------------------------------------------------------------------- /OpenEdge ABL.sublime-package/temp-table.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | def tt 15 | dtt 16 | 17 | 18 | 19 | Insère une TEMP-TABLE 20 | 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Progress ABL 4GL support for Sublime Text 3 2 | 3 | By [GabSoftware](http://www.gabsoftware.com/) 4 | 5 | If you want to add support for [Progress](http://www.progress.com/) ABL 4GL in [Sublime Text](http://www.sublimetext.com/), you can use this syntax plugin. 6 | A ready-to-install package is located in the `dist` directory. 7 | 8 | ## Building 9 | 10 | 1. Zip the **content** of the OpenEdge ABL.sublime-package directory (not the directory itself) 11 | 2. Rename the archive to "OpenEdge ABL.sublime-package" (without .zip in the end of the file name) 12 | 13 | ## Installing or modifying 14 | 15 | 1. Close Sublime Text if necessary 16 | 2. Locate the data directory of Sublime Text 3 : 17 | * On Windows, it is located in `%APPDATA%\Sublime Text 3` 18 | * On Linux, it is located in `~/.config/sublime-text-3` 19 | * On OS X, it is located in `~/Library/Application Support/Sublime Text 3` 20 | 3. In the data directory, place the package `OpenEdge ABL.sublime-package` in the `Installed Packages` directory. 21 | 4. In the data directory (but in `%LOCALAPPDATA%\Sublime Text 3` in Windows!), delete the `Cache/OpenEdge ABL` directory 22 | 5. Restart Sublime Text 23 | 6. You may need to open each progress file type (.p, .cls, .i, .w...) and associate them with the new syntax scheme: 24 | `View > Syntax > Open all with current extension as... > OpenEdge ABL` 25 | 26 | ## "Check Syntax,Compile,Run" support with auto capitalization of keywords 27 | 28 | **Note: this isonly available starting from Progress 11.x** 29 | 30 | It is possible to get the "Check Syntax,Compile,Run" feature of OpenEdge working in Sublime Text. To do so, you can follow these steps : 31 | 32 | 1. Makes sure you have saved your project, this creates a .sublime-project 33 | 2. Update your .sublime-project to add the settings.abl node 34 | ``` 35 | { 36 | "folders": 37 | [ 38 | { 39 | "path": "." 40 | } 41 | ], 42 | "settings": 43 | { 44 | "abl": 45 | { 46 | "dlc": "/path/to/dlc", // Path to your DLC 47 | "hooks": 48 | { 49 | "pre": "/code/to/run/pre.p" // This code will be run before compile,checking syntax or running but after propath bellow has been set 50 | }, 51 | "pf": "conf/sublime.pf", // this path can be fully qualified or relative to the sublime-project file 52 | "propath": 53 | [ 54 | "src/module1", // these paths can be fully qualified or relative to the sublime-project file 55 | "src/module2" 56 | ], 57 | "db": [ 58 | "-db /path/to/db -ld somedb -1", // DB connection strings 59 | "-db /path/to/db2 -ld somedb2 -1" 60 | ], 61 | "uppercase_keywords": true // Do you want sublime to capitalize ABL Keywords 62 | } 63 | } 64 | } 65 | ``` 66 | 3. Hitting CTRL + SHIFT + B will give you a list 67 | - ABL : checks syntax 68 | - ABL - Check Syntax : checks syntax 69 | - ABL - Compile : compiles 70 | - ABL - Run Batch : runs code in an \_progres -b session and returns messages to the sublime console 71 | - ABL - Run GUI : runs the code in an prowin/32.exe 72 | 3. You can now repeat your last choice by hitting CTRL + B 73 | 74 | This doesnt work on untitled buffers in sublime, the buffer must have a filename 75 | 76 | ## Notes 77 | 78 | This product is not supported by Progress. 79 | -------------------------------------------------------------------------------- /dist/OpenEdge ABL.sublime-package: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gabsoftware/progress-abl-4gl-sublime-text/972058871ff114400a7cb7332ecee9c5643662fc/dist/OpenEdge ABL.sublime-package --------------------------------------------------------------------------------