~ubuntu-branches/ubuntu/vivid/kate/vivid-updates

« back to all changes in this revision

Viewing changes to part/script/data/indentation/cmake.js

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2014-12-04 16:49:41 UTC
  • mfrom: (1.6.6)
  • Revision ID: package-import@ubuntu.com-20141204164941-l3qbvsly83hhlw2v
Tags: 4:14.11.97-0ubuntu1
* New upstream release
* Update build-deps and use pkg-kde v3 for Qt 5 build
* kate-data now kate5-data for co-installability

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* kate-script
2
 
 * name: CMake
3
 
 * license: LGPL
4
 
 * author: Alex Turbov <i.zaufi@gmail.com>
5
 
 * revision: 1
6
 
 * kate-version: 3.4
7
 
 * required-syntax-style: CMake
8
 
 * indent-languages: CMake
9
 
 *
10
 
 * This file is part of the Kate Project.
11
 
 *
12
 
 * This library is free software; you can redistribute it and/or
13
 
 * modify it under the terms of the GNU Library General Public
14
 
 * License as published by the Free Software Foundation; either
15
 
 * version 2 of the License, or (at your option) any later version.
16
 
 *
17
 
 * This library is distributed in the hope that it will be useful,
18
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20
 
 * Library General Public License for more details.
21
 
 *
22
 
 * You should have received a copy of the GNU Library General Public License
23
 
 * along with this library; see the file COPYING.LIB.  If not, write to
24
 
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25
 
 * Boston, MA 02110-1301, USA.
26
 
 */
27
 
 
28
 
/**
29
 
 * Some settings it assumes being in effect:
30
 
 * indent-width 4;
31
 
 * space-indent true;
32
 
 *
33
 
 * \todo Better to check (assert) some of that modelines...
34
 
 */
35
 
 
36
 
// required katepart js libraries
37
 
require ("cmake_indenter_config.js")
38
 
require ("range.js");
39
 
require ("string.js");
40
 
require ("utils.js")
41
 
require ("underscore.js")
42
 
 
43
 
triggerCharacters = "()$<{\"";
44
 
 
45
 
//BEGIN Configuration
46
 
var debugMode = false;
47
 
//END Configuration
48
 
 
49
 
/// Global var to store indentation width for current document type
50
 
var gIndentWidth = 4;
51
 
/// Map of CMake calls where a key is the \e end of a corresponding \e start call
52
 
var END_BEGIN_CALL_PAIRS = {
53
 
    "endfunction": "function"
54
 
  , "endmacro": "macro"
55
 
  , "endforeach" : "foreach"
56
 
  , "endif" : {target: ["if", "else", "elseif"], push: ["endif"], pop: ["if"]}
57
 
  , "elseif" : {target: ["if", "elseif"], push: ["endif"], pop: ["if"]}
58
 
  , "else" : {target: ["if", "elseif"], push: ["endif"], pop: ["if"]}
59
 
  , "endwhile" : "while"
60
 
};
61
 
/// List of CMake commands which introduce indentation decrease
62
 
var CONTROL_FLOW_CALLS_TO_UNINDENT_AFTER = [
63
 
    "break", "return"
64
 
];
65
 
/// List of CMake commands which introduce indentation increase
66
 
var CONTROL_FLOW_CALLS_TO_INDENT_AFTER = [
67
 
    "function", "macro", "foreach", "if", "else", "elseif", "while"
68
 
];
69
 
/// List of CMake calls w/o (and/or all optional) parameters
70
 
var PARAMETERLESS_CALLS = [
71
 
    "break", "else", "elseif", "enable_testing", "endforeach", "endif", "endmacro", "endwhile", "return"
72
 
];
73
 
/// List of CMake command options which have parameter(s)
74
 
var INDENT_AFTER_OPTIONS = [
75
 
    "OUTPUT"                                                // add_custom_command
76
 
  , "COMMAND"                                               // add_custom_command, add_custom_target, add_test, execute_process, if
77
 
  , "ARGS"                                                  // add_custom_command, try_run
78
 
  , "MAIN_DEPENDENCY"                                       // add_custom_command
79
 
  , "DEPENDS"                                               // add_custom_command, add_custom_target
80
 
  , "IMPLICIT_DEPENDS"                                      // add_custom_command
81
 
  , "WORKING_DIRECTORY"                                     // add_custom_command, add_custom_target, add_test, execute_process
82
 
  , "COMMENT"                                               // add_custom_command, add_custom_target
83
 
  , "TARGET"                                                // add_custom_command, build_command, get_property, if, set_property
84
 
  , "SOURCES"                                               // add_custom_target, try_compile
85
 
  , "ALIAS"                                                 // add_executable
86
 
  , "OBJECT"                                                // add_library, add_library
87
 
  , "NAME"                                                  // add_test
88
 
  , "CONFIGURATIONS"                                        // add_test, install
89
 
  , "CONFIGURATION"                                         // build_command
90
 
  , "PROJECT_NAME"                                          // build_command
91
 
  , "RESULT"                                                // cmake_host_system_information
92
 
  , "QUERY"                                                 // cmake_host_system_information
93
 
  , "VERSION"                                               // cmake_minimum_required, cmake_policy
94
 
  , "SET"                                                   // cmake_policy
95
 
  , "GET"                                                   // cmake_policy, list
96
 
  , "NEWLINE_STYLE"                                         // configure_file
97
 
  , "EXTRA_INCLUDE"                                         // create_test_sourcelist
98
 
  , "FUNCTION"                                              // create_test_sourcelist
99
 
  , "PROPERTY"                                              // define_property, get_property, set_property
100
 
  , "BRIEF_DOCS"                                            // define_property
101
 
  , "FULL_DOCS"                                             // define_property
102
 
  , "TIMEOUT"                                               // execute_process, file
103
 
  , "RESULT_VARIABLE"                                       // execute_process, include
104
 
  , "OUTPUT_VARIABLE"                                       // execute_process, try_compile, try_run
105
 
  , "ERROR_VARIABLE"                                        // execute_process
106
 
  , "INPUT_FILE"                                            // execute_process
107
 
  , "OUTPUT_FILE"                                           // execute_process
108
 
  , "ERROR_FILE"                                            // execute_process
109
 
  , "TARGETS"                                               // export, install
110
 
  , "NAMESPACE"                                             // export, install
111
 
  , "FILE"                                                  // export, install
112
 
  , "PACKAGE"                                               // export
113
 
  , "WRITE"                                                 // file
114
 
  , "APPEND"                                                // file, list
115
 
  , "READ"                                                  // file
116
 
  , "LIMIT"                                                 // file
117
 
  , "OFFSET"                                                // file
118
 
  , "STRINGS"                                               // file
119
 
  , "LIMIT_COUNT"                                           // file
120
 
  , "LIMIT_INPUT"                                           // file
121
 
  , "LIMIT_OUTPUT"                                          // file
122
 
  , "LENGTH_MINIMUM"                                        // file
123
 
  , "LENGTH_MAXIMUM"                                        // file
124
 
  , "REGEX"                                                 // file, string
125
 
  , "GLOB"                                                  // file
126
 
  , "RELATIVE"                                              // file
127
 
  , "GLOB_RECURSE"                                          // file
128
 
  , "RENAME"                                                // file, install
129
 
  , "REMOVE"                                                // file
130
 
  , "REMOVE_RECURSE"                                        // file
131
 
  , "MAKE_DIRECTORY"                                        // file
132
 
  , "RELATIVE_PATH"                                         // file
133
 
  , "TO_CMAKE_PATH"                                         // file
134
 
  , "TO_NATIVE_PATH"                                        // file
135
 
  , "DOWNLOAD"                                              // file
136
 
  , "INACTIVITY_TIMEOUT"                                    // file
137
 
  , "STATUS"                                                // file
138
 
  , "LOG"                                                   // file
139
 
  , "EXPECTED_HASH"                                         // file
140
 
  , "EXPECTED_MD5"                                          // file
141
 
  , "TLS_VERIFY"                                            // file
142
 
  , "TLS_CAINFO"                                            // file
143
 
  , "UPLOAD"                                                // file
144
 
  , "TIMESTAMP"                                             // file, string
145
 
  , "GENERATE"                                              // file
146
 
  , "INPUT"                                                 // file
147
 
  , "CONTENT"                                               // file
148
 
  , "CONDITION"                                             // file
149
 
  , "COPY"                                                  // file
150
 
  , "INSTALL"                                               // file
151
 
  , "DESTINATION"                                           // file, install
152
 
  , "FILE_PERMISSIONS"                                      // file, install
153
 
  , "DIRECTORY_PERMISSIONS"                                 // file, install
154
 
  , "FILES_MATCHING"                                        // file, install
155
 
  , "PATTERN"                                               // file, install
156
 
  , "PERMISSIONS"                                           // file, install
157
 
  , "EXCLUDE"                                               // file, install, load_cache
158
 
  , "NAMES"                                                 // find_file, find_library, find_package, find_path, find_program
159
 
  , "HINTS"                                                 // find_file, find_library, find_package, find_path, find_program
160
 
  , "ENV"                                                   // find_file, find_library, find_path, find_program
161
 
  , "PATHS"                                                 // find_file, find_library, find_package, find_path, find_program
162
 
  , "PATH_SUFFIXES"                                         // find_file, find_library, find_package, find_path, find_program
163
 
  , "DOC"                                                   // find_file, find_library, find_path, find_program
164
 
  , "REQUIRED"                                              // find_package
165
 
  , "COMPONENTES"                                           // find_package
166
 
  , "OPTIONAL_COMPONENTES"                                  // find_package
167
 
  , "CONFIGS"                                               // find_package
168
 
  , "DIRECTORY"                                             // get_directory_property, get_property, install, set_property
169
 
  , "DEFINITION"                                            // get_directory_property
170
 
  , "PROGRAM"                                               // get_filename_component
171
 
  , "PROGRAM_ARGS"                                          // get_filename_component
172
 
  , "SOURCE"                                                // get_property, set_property
173
 
  , "TEST"                                                  // get_property, set_property
174
 
  , "CACHE"                                                 // get_property, set, set_property
175
 
  , "NOT"                                                   // if
176
 
  , "AND"                                                   // if
177
 
  , "OR"                                                    // if
178
 
  , "POLICY"                                                // if
179
 
  , "EXISTS"                                                // if
180
 
  , "IS_NEWER_THAN"                                         // if
181
 
  , "IS_DIRECTORY"                                          // if
182
 
  , "IS_SYMLINK"                                            // if
183
 
  , "IS_ABSOLUTE"                                           // if
184
 
  , "MATCHES"                                               // if
185
 
  , "LESS"                                                  // if, string
186
 
  , "GREATER"                                               // if, string
187
 
  , "EQUAL"                                                 // if, string
188
 
  , "STRLESS"                                               // if
189
 
  , "STRGREATER"                                            // if
190
 
  , "STREQUAL"                                              // if
191
 
  , "VERSION_LESS"                                          // if
192
 
  , "VERSION_GREATER"                                       // if
193
 
  , "VERSION_EQUAL"                                         // if
194
 
  , "DEFINED"                                               // if
195
 
  , "TYPE"                                                  // include_external_msproject
196
 
  , "GUID"                                                  // include_external_msproject
197
 
  , "PLATFORM"                                              // include_external_msproject
198
 
  , "EXPORT"                                                // install
199
 
  , "ARCHIVE"                                               // install
200
 
  , "LIBRARY"                                               // install
201
 
  , "RUNTIME"                                               // install
202
 
  , "FRAMEWORK"                                             // install
203
 
  , "BUNDLE"                                                // install
204
 
  , "PRIVATE_HEADER"                                        // install
205
 
  , "PUBLIC_HEADER"                                         // install
206
 
  , "RESOURCE"                                              // install
207
 
  , "COMPONENT"                                             // install
208
 
  , "FILES"                                                 // install
209
 
  , "PROGRAMS"                                              // install
210
 
  , "SCRIPT"                                                // install
211
 
  , "CODE"                                                  // install
212
 
  , "LENGTH"                                                // list, string
213
 
  , "FIND"                                                  // list, string
214
 
  , "INSERT"                                                // list
215
 
  , "REMOVE_ITEM"                                           // list
216
 
  , "REMOVE_AT"                                             // list
217
 
  , "REMOVE_DUPLICATES"                                     // list
218
 
  , "REVERSE"                                               // list
219
 
  , "SORT"                                                  // list
220
 
  , "READ_WITH_PREFIX"                                      // load_cache
221
 
  , "INCLUDE_INTERNALS"                                     // load_cache
222
 
  , "EXPR"                                                  // math
223
 
  , "UNIX_COMMAND"                                          // separate_arguments
224
 
  , "WINDOWS_COMMAND"                                       // separate_arguments
225
 
    // set_directory_properties, set_source_files_properties, set_target_properties, set_tests_properties
226
 
  , "PROPERTIES"
227
 
  , "REGULAR_EXPRESSION"                                    // source_group
228
 
  , "FILES"                                                 // source_group
229
 
  , "MATCH"                                                 // string
230
 
  , "MATCHALL"                                              // string
231
 
  , "REPLACE"                                               // string
232
 
  , "COMPARE"                                               // string
233
 
  , "NOTEQUAL"                                              // string
234
 
  , "ASCII"                                                 // string
235
 
  , "CONFIGURE"                                             // string
236
 
  , "TOUPPER"                                               // string
237
 
  , "TOLOWER"                                               // string
238
 
  , "SUBSTRING"                                             // string
239
 
  , "STRIP"                                                 // string
240
 
  , "RANDOM"                                                // string
241
 
  , "ALPHABET"                                              // string
242
 
  , "RANDOM_SEED"                                           // string
243
 
  , "MAKE_C_IDENTIFIER"                                     // string
244
 
  , "INTERFACE"                                             // target_compile_definitions, target_compile_options, target_include_directories
245
 
  , "PUBLIC"                                                // target_compile_definitions, target_compile_options, target_include_directories
246
 
  , "PRIVATE"                                               // target_compile_definitions, target_compile_options, target_include_directories
247
 
  , "LINK_PRIVATE"                                          // target_link_libraries
248
 
  , "LINK_PUBLIC"                                           // target_link_libraries
249
 
  , "CMAKE_FLAGS"                                           // try_compile, try_run
250
 
  , "COMPILE_DEFINITIONS"                                   // try_compile, try_run
251
 
  , "LINK_LIBRARIES"                                        // try_compile
252
 
  , "COPY_FILE"                                             // try_compile
253
 
  , "COPY_FILE_ERROR"                                       // try_compile
254
 
  , "COMPILE_OUTPUT_VARIABLE"                               // try_run
255
 
  , "RUN_OUTPUT_VARIABLE"                                   // try_run
256
 
];
257
 
 
258
 
 
259
 
/**
260
 
 * \brief Handle \c ENTER between parenthesis
261
 
 */
262
 
function tryParenthesisSplit_ch(cursor)
263
 
{
264
 
    var result = -1;
265
 
 
266
 
    if (isStringOrComment(cursor.line - 1, cursor.column))
267
 
        return result;                                      // Do nothing for comments and strings
268
 
 
269
 
    // Is ENTER was pressed right after '('?
270
 
    if (document.lastChar(cursor.line - 1) == '(')
271
 
    {
272
 
        // Yep, lets get align of the previous line
273
 
        var prev_line_indent = document.firstColumn(cursor.line - 1);
274
 
        result = prev_line_indent + gIndentWidth;
275
 
        // Indent a closing ')' if ENTER was pressed between '(|)'
276
 
        if (document.firstChar(cursor.line) == ')')
277
 
        {
278
 
            document.insertText(
279
 
                cursor.line
280
 
              , cursor.column
281
 
              , "\n" + String().fill(' ', prev_line_indent + gIndentWidth / 2)
282
 
              );
283
 
            view.setCursorPosition(cursor.line, cursor.column);
284
 
        }
285
 
    }
286
 
 
287
 
    if (result != -1)
288
 
    {
289
 
        dbg("tryParenthesisSplit_ch: result =", result);
290
 
    }
291
 
    return result;
292
 
}
293
 
 
294
 
/**
295
 
 * \brief Indent after some control flow CMake calls
296
 
 */
297
 
function tryIndentAfterControlFlowCalls_ch(cursor)
298
 
{
299
 
    var result = -1;
300
 
 
301
 
    if (isStringOrComment(cursor.line - 1, cursor.column))
302
 
        return result;                                      // Do nothing for comments and strings
303
 
 
304
 
    var prev_line_indent = document.firstColumn(cursor.line - 1);
305
 
    var first_prev_line_word = document.wordAt(cursor.line - 1, prev_line_indent).toLowerCase();
306
 
    dbg("tryControlFlowCalls_ch: first_prev_line_word =", first_prev_line_word);
307
 
    if (CONTROL_FLOW_CALLS_TO_INDENT_AFTER.indexOf(first_prev_line_word) != -1)
308
 
    {
309
 
        result = prev_line_indent + gIndentWidth;
310
 
    }
311
 
    else if (CONTROL_FLOW_CALLS_TO_UNINDENT_AFTER.indexOf(first_prev_line_word) != -1)
312
 
    {
313
 
        result = prev_line_indent - gIndentWidth;
314
 
    }
315
 
 
316
 
    if (result != -1)
317
 
    {
318
 
        dbg("tryControlFlowCalls_ch: result =", result);
319
 
    }
320
 
    return result;
321
 
}
322
 
 
323
 
/**
324
 
 * \brief Unindent after dandling ')'
325
 
 */
326
 
function tryAfterClosingParensis_ch(cursor)
327
 
{
328
 
    var result = -1;
329
 
 
330
 
    if (isStringOrComment(cursor.line - 1, cursor.column))
331
 
        return result;                                      // Do nothing for comments and strings
332
 
 
333
 
    // Check if dandling ')' present on a previous line
334
 
    var prev_line = document.prevNonEmptyLine(cursor.line - 1);
335
 
    dbg("tryAfterClosingParensis_ch: prev_line =", prev_line);
336
 
    var first_column = document.firstColumn(prev_line);
337
 
    if (document.charAt(prev_line, first_column) == ')')
338
 
        result = first_column - (gIndentWidth / 2);
339
 
 
340
 
    if (result != -1)
341
 
    {
342
 
        dbg("tryAfterClosingParensis_ch: result =", result);
343
 
    }
344
 
    return result;
345
 
}
346
 
 
347
 
/**
348
 
 * \brief Indent after parameterless command options
349
 
 *
350
 
 * It is common way to format options w/ parameters like this:
351
 
 * \code
352
 
 *  install(
353
 
 *      DIRECTORY ${name}
354
 
 *      DESTINATION ${DATA_INSTALL_DIR}/kate/pate
355
 
 *      FILES_MATCHING
356
 
 *          PATTERN "*.py"
357
 
 *          PATTERN "*.ui"
358
 
 *          PATTERN "*_ui.rc"
359
 
 *          PATTERN "__pycache__*" EXCLUDE
360
 
 *     )
361
 
 * \endcode
362
 
 *
363
 
 * I.e. do indent for long parameter lists.
364
 
 * This function recognize parameterless options (and do not indent after them),
365
 
 * for everything else it adds an extra indentation...
366
 
 */
367
 
function tryIndentCommandOptions_ch(cursor)
368
 
{
369
 
    var result = -1;
370
 
 
371
 
    if (isStringOrComment(cursor.line - 1, cursor.column))
372
 
        return result;                                      // Do nothing for comments and strings
373
 
 
374
 
    // Get last word from a previous line
375
 
    var last_word = document.wordAt(cursor.line - 1, document.lastColumn(cursor.line - 1));
376
 
 
377
 
    // ATTENTION Kate will return the last word "TARGET" for text like this: "TARGET)",
378
 
    // which is not what we've wanted... so before continue lets make sure that we've
379
 
    // got that we wanted...
380
 
    if (last_word[last_word.length - 1] != document.lastChar(cursor.line - 1))
381
 
        return result;
382
 
 
383
 
    dbg("tryIndentCommandOptions_ch: last_word =", last_word);
384
 
    result = document.firstColumn(cursor.line - 1)
385
 
      + (INDENT_AFTER_OPTIONS.indexOf(last_word) != -1 ? gIndentWidth : 0)
386
 
      ;
387
 
 
388
 
    if (result != -1)
389
 
    {
390
 
        dbg("tryIndentCommandOptions_ch: result =", result);
391
 
    }
392
 
    return result;
393
 
}
394
 
 
395
 
/**
396
 
 * \brief Handle \c ENTER key
397
 
 */
398
 
function caretPressed(cursor)
399
 
{
400
 
    var result = -1;
401
 
    var line = cursor.line;
402
 
 
403
 
    // Dunno what to do if previous line isn't available
404
 
    if (line - 1 < 0)
405
 
        return result;                                      // Nothing (dunno) to do if no previous line...
406
 
 
407
 
    // Register all indent functions
408
 
    var handlers = [
409
 
        tryParenthesisSplit_ch                              // Handle ENTER between parenthesis
410
 
      , tryIndentAfterControlFlowCalls_ch                   // Indent after some control flow CMake calls
411
 
      , tryAfterClosingParensis_ch                          // Unindent after dandling ')'
412
 
      , tryIndentCommandOptions_ch                          // Indent after parameterless command options
413
 
      ];
414
 
 
415
 
    // Apply all all functions until result gets changed
416
 
    for (
417
 
        var i = 0
418
 
      ; i < handlers.length && result == -1
419
 
      ; result = handlers[i++](cursor)
420
 
      );
421
 
 
422
 
    return result;
423
 
}
424
 
 
425
 
/**
426
 
 * \brief Try to unindent current call when <tt>(</tt> has pressed
427
 
 */
428
 
function tryUnindentCall(cursor)
429
 
{
430
 
    var result = -2;
431
 
 
432
 
    if (isStringOrComment(cursor.line, cursor.column))
433
 
        return result;                                      // Do nothing for comments and strings
434
 
 
435
 
    // Check the word before current cursor position
436
 
    var call_name = document.wordAt(cursor.line, cursor.column - 1).toLowerCase();
437
 
    dbg("tryUnindentCall: call_name =", call_name);
438
 
    var end_calls = _.keys(END_BEGIN_CALL_PAIRS);
439
 
    var stack_level = 0;
440
 
    if (_.indexOf(end_calls, call_name) != -1)
441
 
    {
442
 
        var lookup_call_name = END_BEGIN_CALL_PAIRS[call_name];
443
 
        dbg("tryUnindentCall: typeof lookup_call_name =", typeof lookup_call_name);
444
 
        var matcher;
445
 
        if (typeof lookup_call_name === "string")
446
 
        {
447
 
            matcher = function(word)
448
 
            {
449
 
                return word == lookup_call_name;
450
 
            };
451
 
        }
452
 
        else if (typeof lookup_call_name === "object")
453
 
        {
454
 
            matcher = function(word)
455
 
            {
456
 
                // dbg("tryUnindentCall: stack_level =", stack_level, ", word =", word);
457
 
                if (_.indexOf(lookup_call_name.push, word) != -1)
458
 
                {
459
 
                    stack_level += 1;
460
 
                    return false;
461
 
                }
462
 
                if (stack_level != 0)
463
 
                {
464
 
                    if (_.indexOf(lookup_call_name.pop, word) != -1)
465
 
                        stack_level -= 1;
466
 
                    return false;
467
 
                }
468
 
                return _.indexOf(lookup_call_name.target, word) != -1;
469
 
            };
470
 
        }
471
 
        else
472
 
        {
473
 
            /// \todo Is there any kind of \c assert() in JavaScript at all?
474
 
            dbg("tryUnindentCall: Unknown type of END_BEGIN_CALL_PAIRS value! Code review required!");
475
 
            return result;
476
 
        }
477
 
 
478
 
        // Ok, lets find the corresponding start call towards document's start...
479
 
        var found_line = -1;
480
 
        for (
481
 
            var line = document.prevNonEmptyLine(cursor.line - 1)
482
 
          ; 0 <= line && found_line == -1
483
 
          ; line = document.prevNonEmptyLine(line - 1)
484
 
          )
485
 
        {
486
 
            var first_word = document.wordAt(line, document.firstColumn(line)).toLowerCase();
487
 
            // dbg("tryUnindentCall: line =", line, ", word =", first_word);
488
 
            if (matcher(first_word))
489
 
            {
490
 
                dbg("tryUnindentCall: Found ", first_word);
491
 
                found_line = line;
492
 
            }
493
 
        }
494
 
 
495
 
        if (found_line != -1)
496
 
        {
497
 
            result = document.firstColumn(found_line);
498
 
            // Add closing parenthesis if none yet
499
 
            // addCharOrJumpOverIt(cursor.line, cursor.column, ')');
500
 
        }
501
 
        else
502
 
        {
503
 
            dbg("tryUnindentCall: Not Found!");
504
 
        }
505
 
    }
506
 
 
507
 
    if (result != -2)
508
 
    {
509
 
        dbg("tryUnindentCall: result =", result);
510
 
    }
511
 
    return result;
512
 
}
513
 
 
514
 
/**
515
 
 * Align closing parenthesis if it is a first character on a line
516
 
 */
517
 
function tryAlignCloseParenthesis(cursor)
518
 
{
519
 
    var result = -2;
520
 
 
521
 
    if (isStringOrComment(cursor.line, cursor.column))
522
 
        return result;                                      // Do nothing for comments and strings
523
 
 
524
 
    if (justEnteredCharIsFirstOnLine(cursor.line, cursor.column, ')'))
525
 
    {
526
 
        // Try to find corresponding open parenthesis
527
 
        var open = document.anchor(cursor.line, cursor.column - 1, '(');
528
 
        dbg("tryAlignCloseParenthesis: Found open brace at", open);
529
 
        if (open.isValid())
530
 
            result = document.firstColumn(open.line) + (gIndentWidth / 2);
531
 
    }
532
 
 
533
 
    if (result != -2)
534
 
    {
535
 
        dbg("tryAlignCloseParenthesis: result =", result);
536
 
    }
537
 
    return result;
538
 
}
539
 
 
540
 
/**
541
 
 * \brief Move cursor out of <tt>'()'</tt> if no parameters required for a given call
542
 
 */
543
 
function tryJumpOutOfParenthesis(cursor)
544
 
{
545
 
    if (isStringOrComment(cursor.line, cursor.column))
546
 
        return;                                             // Do nothing for comments and strings
547
 
 
548
 
    var first_word = document.wordAt(cursor.line, document.firstColumn(cursor.line)).toLowerCase();
549
 
    dbg("tryJumpOutOfParenthesis: @"+cursor.line+","+cursor.column+", char="+document.charAt(cursor));
550
 
    if (PARAMETERLESS_CALLS.indexOf(first_word) != -1)
551
 
        addCharOrJumpOverIt(cursor.line, cursor.column, ')')
552
 
}
553
 
 
554
 
/**
555
 
 * \brief Append <tt>'{}'</tt> after \c '$'
556
 
 */
557
 
function insertVariableExpansion(cursor)
558
 
{
559
 
    if (!cmi_cfg_vgShortcut || isComment(cursor.line, cursor.column))
560
 
        return;                                             // Do nothing for comments
561
 
 
562
 
    var next_ch = document.charAt(cursor);
563
 
    dbg("insertVariableExpansion: next_ch ='"+next_ch+"'");
564
 
    if (!next_ch.match(/[A-Za-z_]/))
565
 
    {
566
 
        if (next_ch != '{')
567
 
            document.insertText(cursor, "{}");
568
 
        view.setCursorPosition(cursor.line, cursor.column + 1);
569
 
    }
570
 
}
571
 
 
572
 
/**
573
 
 * \brief Handle <tt>'$'</tt> character
574
 
 *
575
 
 * Here is possble few transformations: if \c '<' pressed after \c '$',
576
 
 * transform <tt>'${<}'</tt> to <tt>'$<>'</tt> to be ready for
577
 
 * generator expression and vise versa.
578
 
 */
579
 
function tryVariableOrGeneratorExpression(cursor, ch)
580
 
{
581
 
    if (!cmi_cfg_vgShortcut || isComment(cursor.line, cursor.column))
582
 
        return;                                             // Do nothing for comments and strings
583
 
 
584
 
    var tail = document.text(
585
 
        cursor.line
586
 
      , document.firstColumn(cursor.line)
587
 
      , cursor.line
588
 
      , cursor.column
589
 
      );
590
 
    var next_ch = document.charAt(cursor);
591
 
    dbg("tryVariableOrGeneratorExpression: tail ='"+tail+"'");
592
 
    var fix_text = function(text)
593
 
    {
594
 
        document.removeText(cursor.line, cursor.column - 2, cursor.line, cursor.column + 1);
595
 
        document.insertText(cursor.line, cursor.column - 2, text);
596
 
        view.setCursorPosition(cursor.line, cursor.column - 1);
597
 
    };
598
 
    if (tail.endsWith("${<") && next_ch == '}')
599
 
    {
600
 
        fix_text("<>");                                     // Transform '${}' -> '$<>'
601
 
    }
602
 
    else if (tail.endsWith("$<{") && next_ch == '>')
603
 
    {
604
 
        fix_text("{}");                                     // Transform '$<>' -> '${}'
605
 
    }
606
 
    else if (tail.endsWith("${{") && next_ch == '}')
607
 
    {
608
 
        // Transform '${{|}' --> '${|}'
609
 
        document.removeText(cursor.line, cursor.column - 1, cursor.line, cursor.column);
610
 
    }
611
 
    else if (tail.endsWith("$<<") && next_ch == '>')
612
 
    {
613
 
        // Transform '$<<|>' --> '$<|>'
614
 
        document.removeText(cursor.line, cursor.column - 1, cursor.line, cursor.column);
615
 
    }
616
 
}
617
 
 
618
 
/**
619
 
 * \brief Open/close string literal
620
 
 *
621
 
 * \attention Autobracket extension w/ add quote char doesn't work
622
 
 * for CMake files (file a BUG?)...
623
 
 */
624
 
function tryString(cursor)
625
 
{
626
 
    if (isComment(cursor.line, cursor.column))
627
 
        return;                                             // Do nothing for comments
628
 
 
629
 
    // NOTE If cursor has a string attribute, then it was an open quote
630
 
    // character just entered...
631
 
    // ATTENTION If cursor positioned at the end of a line,
632
 
    // isString() returns 'false' for some unknown reason...
633
 
    // so check the attribute for the just entered quote symbol...
634
 
    if (isString(cursor.line, cursor.column - 1))
635
 
    {
636
 
        // Check if next char is not a quote already
637
 
        // and/or maybe some punctualtion... Particularly
638
 
        // ')' remains after some function call -- i.e. smth like
639
 
        //   message(STATUS "|)
640
 
        // or just entered quot char is a first on a line and
641
 
        // no other chars are here...
642
 
        var ch = document.charAt(cursor);
643
 
        if ((ch != '"' && (ch == ')' || ch == ' '))
644
 
          || (justEnteredCharIsFirstOnLine(cursor.line, cursor.column, '"')
645
 
              && document.lineLength(cursor.line) == cursor.column
646
 
              )
647
 
          )
648
 
        {
649
 
            document.insertText(cursor, '"')
650
 
            view.setCursorPosition(cursor);
651
 
        }
652
 
    }                                                       // Do nothing for closing quote char
653
 
}
654
 
 
655
 
/**
656
 
 * \brief Process one character
657
 
 *
658
 
 * NOTE Cursor positioned right after just entered character and has \c +1 in column.
659
 
 */
660
 
function processChar(line, ch)
661
 
{
662
 
    var result = -2;                                        // By default, do nothing...
663
 
    var cursor = view.cursorPosition();
664
 
    if (!cursor)
665
 
        return result;
666
 
 
667
 
    document.editBegin();
668
 
    // Check if char under cursor is the same as just entered,
669
 
    // and if so, remove it... to make it behave like "overwrite" mode
670
 
    if (ch != ' ' && document.charAt(cursor) == ch)
671
 
        document.removeText(line, cursor.column, line, cursor.column + 1);
672
 
 
673
 
    switch (ch)
674
 
    {
675
 
        case '\n':
676
 
            result = caretPressed(cursor);
677
 
            break;
678
 
        case '(':
679
 
            result = tryUnindentCall(cursor);
680
 
            tryJumpOutOfParenthesis(cursor);
681
 
            break;
682
 
        case ')':
683
 
            result = tryAlignCloseParenthesis(cursor);
684
 
            break;
685
 
        case '$':
686
 
            insertVariableExpansion(cursor);
687
 
            break;
688
 
        case '{':
689
 
        case '<':
690
 
            tryVariableOrGeneratorExpression(cursor, ch);
691
 
            break;
692
 
        case '"':
693
 
            tryString(cursor);
694
 
            break;
695
 
        default:
696
 
            break;                                          // Nothing to do...
697
 
    }
698
 
 
699
 
    document.editEnd();
700
 
    return result;
701
 
}
702
 
 
703
 
/**
704
 
 * Try to align a given line
705
 
 * \todo More actions
706
 
 */
707
 
function indentLine(line)
708
 
{
709
 
    dbg(">> Going to indent line ", line);
710
 
    var cursor = new Cursor(line, document.firstColumn(line) + 1);
711
 
    var result = tryUnindentCall(cursor);
712
 
    if (result == -2)
713
 
        result = tryAlignCloseParenthesis(cursor);
714
 
    cursor = new Cursor(line, document.firstColumn(line));
715
 
    if (result == -2)
716
 
        result = caretPressed(cursor);
717
 
    dbg("indentLine: result =", result);
718
 
 
719
 
    if (result == -2)                                       // Still dunno what to do?
720
 
        result = -1;                                        // ... just align according a previous non empty line
721
 
    return result;
722
 
}
723
 
 
724
 
/**
725
 
 * \brief Process a newline or one of \c triggerCharacters character.
726
 
 *
727
 
 * This function is called whenever the user hits \c ENTER key.
728
 
 *
729
 
 * It gets three arguments: \c line, \c indentwidth in spaces and typed character
730
 
 *
731
 
 * Called for each newline (<tt>ch == \n</tt>) and all characters specified in
732
 
 * the global variable \c triggerCharacters. When calling \e Tools->Align
733
 
 * the variable \c ch is empty, i.e. <tt>ch == ''</tt>.
734
 
 */
735
 
function indent(line, indentWidth, ch)
736
 
{
737
 
    // NOTE Update some global variables
738
 
    gIndentWidth = indentWidth;
739
 
 
740
 
    dbg("indentWidth: " + indentWidth);
741
 
    dbg("      gMode: " + document.highlightingModeAt(view.cursorPosition()));
742
 
    dbg("      gAttr: " + document.attributeName(view.cursorPosition()));
743
 
    dbg("       line: " + line);
744
 
    dbg("         ch: '" + ch + "'");
745
 
 
746
 
    if (ch != "")
747
 
        return processChar(line, ch);
748
 
 
749
 
    return indentLine(line);
750
 
}
751
 
 
752
 
// kate: space-indent on; indent-width 4; replace-tabs on;
753
 
 
754
 
/**
755
 
 * \todo Move string/comment checks to \c caretPressed() instead of particular function.
756
 
 */