comparison src/misc1.c @ 6030:9a4efda75b5e v7.4.355

updated for version 7.4.355 Problem: Several problems with Javascript indenting. Solution: Improve Javascript indenting.
author Bram Moolenaar <bram@vim.org>
date Thu, 03 Jul 2014 22:57:55 +0200
parents ad005d0114c1
children d3a674f6c737
comparison
equal deleted inserted replaced
6029:13aa635aed9f 6030:9a4efda75b5e
5380 */ 5380 */
5381 5381
5382 static char_u *cin_skipcomment __ARGS((char_u *)); 5382 static char_u *cin_skipcomment __ARGS((char_u *));
5383 static int cin_nocode __ARGS((char_u *)); 5383 static int cin_nocode __ARGS((char_u *));
5384 static pos_T *find_line_comment __ARGS((void)); 5384 static pos_T *find_line_comment __ARGS((void));
5385 static int cin_has_js_key __ARGS((char_u *text));
5385 static int cin_islabel_skip __ARGS((char_u **)); 5386 static int cin_islabel_skip __ARGS((char_u **));
5386 static int cin_isdefault __ARGS((char_u *)); 5387 static int cin_isdefault __ARGS((char_u *));
5387 static char_u *after_label __ARGS((char_u *l)); 5388 static char_u *after_label __ARGS((char_u *l));
5388 static int get_indent_nolabel __ARGS((linenr_T lnum)); 5389 static int get_indent_nolabel __ARGS((linenr_T lnum));
5389 static int skip_label __ARGS((linenr_T, char_u **pp)); 5390 static int skip_label __ARGS((linenr_T, char_u **pp));
5408 static int cin_ends_in __ARGS((char_u *, char_u *, char_u *)); 5409 static int cin_ends_in __ARGS((char_u *, char_u *, char_u *));
5409 static int cin_starts_with __ARGS((char_u *s, char *word)); 5410 static int cin_starts_with __ARGS((char_u *s, char *word));
5410 static int cin_skip2pos __ARGS((pos_T *trypos)); 5411 static int cin_skip2pos __ARGS((pos_T *trypos));
5411 static pos_T *find_start_brace __ARGS((void)); 5412 static pos_T *find_start_brace __ARGS((void));
5412 static pos_T *find_match_paren __ARGS((int)); 5413 static pos_T *find_match_paren __ARGS((int));
5414 static pos_T *find_match_char __ARGS((int c, int ind_maxparen));
5413 static int corr_ind_maxparen __ARGS((pos_T *startpos)); 5415 static int corr_ind_maxparen __ARGS((pos_T *startpos));
5414 static int find_last_paren __ARGS((char_u *l, int start, int end)); 5416 static int find_last_paren __ARGS((char_u *l, int start, int end));
5415 static int find_match __ARGS((int lookfor, linenr_T ourscope)); 5417 static int find_match __ARGS((int lookfor, linenr_T ourscope));
5416 static int cin_is_cpp_namespace __ARGS((char_u *)); 5418 static int cin_is_cpp_namespace __ARGS((char_u *));
5417 5419
5492 } 5494 }
5493 return NULL; 5495 return NULL;
5494 } 5496 }
5495 5497
5496 /* 5498 /*
5499 * Return TRUE if "text" starts with "key:".
5500 */
5501 static int
5502 cin_has_js_key(text)
5503 char_u *text;
5504 {
5505 char_u *s = skipwhite(text);
5506 int quote = 0;
5507
5508 if (*s == '\'' || *s == '"')
5509 {
5510 /* can be 'key': or "key": */
5511 quote = *s;
5512 ++s;
5513 }
5514 if (!vim_isIDc(*s)) /* need at least one ID character */
5515 return FALSE;
5516
5517 while (vim_isIDc(*s))
5518 ++s;
5519 if (*s == quote)
5520 ++s;
5521
5522 s = cin_skipcomment(s);
5523
5524 /* "::" is not a label, it's C++ */
5525 return (*s == ':' && s[1] != ':');
5526 }
5527
5528 /*
5497 * Check if string matches "label:"; move to character after ':' if true. 5529 * Check if string matches "label:"; move to character after ':' if true.
5530 * "*s" must point to the start of the label, if there is one.
5498 */ 5531 */
5499 static int 5532 static int
5500 cin_islabel_skip(s) 5533 cin_islabel_skip(s)
5501 char_u **s; 5534 char_u **s;
5502 { 5535 {
6619 */ 6652 */
6620 static pos_T * 6653 static pos_T *
6621 find_match_paren(ind_maxparen) /* XXX */ 6654 find_match_paren(ind_maxparen) /* XXX */
6622 int ind_maxparen; 6655 int ind_maxparen;
6623 { 6656 {
6657 return find_match_char('(', ind_maxparen);
6658 }
6659
6660 static pos_T *
6661 find_match_char(c, ind_maxparen) /* XXX */
6662 int c;
6663 int ind_maxparen;
6664 {
6624 pos_T cursor_save; 6665 pos_T cursor_save;
6625 pos_T *trypos; 6666 pos_T *trypos;
6626 static pos_T pos_copy; 6667 static pos_T pos_copy;
6627 6668
6628 cursor_save = curwin->w_cursor; 6669 cursor_save = curwin->w_cursor;
6629 if ((trypos = findmatchlimit(NULL, '(', 0, ind_maxparen)) != NULL) 6670 if ((trypos = findmatchlimit(NULL, c, 0, ind_maxparen)) != NULL)
6630 { 6671 {
6631 /* check if the ( is in a // comment */ 6672 /* check if the ( is in a // comment */
6632 if ((colnr_T)cin_skip2pos(trypos) > trypos->col) 6673 if ((colnr_T)cin_skip2pos(trypos) > trypos->col)
6633 trypos = NULL; 6674 trypos = NULL;
6634 else 6675 else
6974 #define LOOKFOR_UNTERM 6 7015 #define LOOKFOR_UNTERM 6
6975 #define LOOKFOR_SCOPEDECL 7 7016 #define LOOKFOR_SCOPEDECL 7
6976 #define LOOKFOR_NOBREAK 8 7017 #define LOOKFOR_NOBREAK 8
6977 #define LOOKFOR_CPP_BASECLASS 9 7018 #define LOOKFOR_CPP_BASECLASS 9
6978 #define LOOKFOR_ENUM_OR_INIT 10 7019 #define LOOKFOR_ENUM_OR_INIT 10
7020 #define LOOKFOR_JS_KEY 11
7021 #define LOOKFOR_NO_COMMA 12
6979 7022
6980 int whilelevel; 7023 int whilelevel;
6981 linenr_T lnum; 7024 linenr_T lnum;
6982 int n; 7025 int n;
6983 int iscase; 7026 int iscase;
6984 int lookfor_break; 7027 int lookfor_break;
6985 int lookfor_cpp_namespace = FALSE; 7028 int lookfor_cpp_namespace = FALSE;
6986 int cont_amount = 0; /* amount for continuation line */ 7029 int cont_amount = 0; /* amount for continuation line */
6987 int original_line_islabel; 7030 int original_line_islabel;
6988 int added_to_amount = 0; 7031 int added_to_amount = 0;
7032 int js_cur_has_key = 0;
6989 7033
6990 /* make a copy, value is changed below */ 7034 /* make a copy, value is changed below */
6991 int ind_continuation = curbuf->b_ind_continuation; 7035 int ind_continuation = curbuf->b_ind_continuation;
6992 7036
6993 /* remember where the cursor was when we started */ 7037 /* remember where the cursor was when we started */
7207 } 7251 }
7208 } 7252 }
7209 } 7253 }
7210 7254
7211 /* 7255 /*
7256 * Are we looking at a ']' that has a match?
7257 */
7258 else if (*skipwhite(theline) == ']'
7259 && (trypos = find_match_char('[', curbuf->b_ind_maxparen)) != NULL)
7260 {
7261 /* align with the line containing the '['. */
7262 amount = get_indent_lnum(trypos->lnum);
7263 }
7264
7265 /*
7212 * Are we inside parentheses or braces? 7266 * Are we inside parentheses or braces?
7213 */ /* XXX */ 7267 */ /* XXX */
7214 else if (((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL 7268 else if (((trypos = find_match_paren(curbuf->b_ind_maxparen)) != NULL
7215 && curbuf->b_ind_java == 0) 7269 && curbuf->b_ind_java == 0)
7216 || (tryposBrace = find_start_brace()) != NULL 7270 || (tryposBrace = find_start_brace()) != NULL
7471 7525
7472 /* add extra indent for a comment */ 7526 /* add extra indent for a comment */
7473 if (cin_iscomment(theline)) 7527 if (cin_iscomment(theline))
7474 amount += curbuf->b_ind_comment; 7528 amount += curbuf->b_ind_comment;
7475 } 7529 }
7476
7477 /*
7478 * Are we at least inside braces, then?
7479 */
7480 else 7530 else
7481 { 7531 {
7532 /*
7533 * We are inside braces, there is a { before this line at the position
7534 * stored in tryposBrace.
7535 */
7482 trypos = tryposBrace; 7536 trypos = tryposBrace;
7483
7484 ourscope = trypos->lnum; 7537 ourscope = trypos->lnum;
7485 start = ml_get(ourscope); 7538 start = ml_get(ourscope);
7486 7539
7487 /* 7540 /*
7488 * Now figure out how indented the line is in general. 7541 * Now figure out how indented the line is in general.
7500 else 7553 else
7501 start_brace = BRACE_AT_START; 7554 start_brace = BRACE_AT_START;
7502 } 7555 }
7503 else 7556 else
7504 { 7557 {
7505 /* 7558 /* That opening brace might have been on a continuation
7506 * that opening brace might have been on a continuation 7559 * line. if so, find the start of the line. */
7507 * line. if so, find the start of the line.
7508 */
7509 curwin->w_cursor.lnum = ourscope; 7560 curwin->w_cursor.lnum = ourscope;
7510 7561
7511 /* 7562 /* Position the cursor over the rightmost paren, so that
7512 * position the cursor over the rightmost paren, so that 7563 * matching it will take us back to the start of the line. */
7513 * matching it will take us back to the start of the line.
7514 */
7515 lnum = ourscope; 7564 lnum = ourscope;
7516 if (find_last_paren(start, '(', ')') 7565 if (find_last_paren(start, '(', ')')
7517 && (trypos = find_match_paren(curbuf->b_ind_maxparen)) 7566 && (trypos = find_match_paren(curbuf->b_ind_maxparen))
7518 != NULL) 7567 != NULL)
7519 lnum = trypos->lnum; 7568 lnum = trypos->lnum;
7520 7569
7521 /* 7570 /* It could have been something like
7522 * It could have been something like
7523 * case 1: if (asdf && 7571 * case 1: if (asdf &&
7524 * ldfd) { 7572 * ldfd) {
7525 * } 7573 * }
7526 */ 7574 */
7527 if ((curbuf->b_ind_js || curbuf->b_ind_keep_case_label) 7575 if ((curbuf->b_ind_js || curbuf->b_ind_keep_case_label)
7533 amount = skip_label(lnum, &l); 7581 amount = skip_label(lnum, &l);
7534 7582
7535 start_brace = BRACE_AT_END; 7583 start_brace = BRACE_AT_END;
7536 } 7584 }
7537 7585
7586 /* For Javascript check if the line starts with "key:". */
7587 if (curbuf->b_ind_js)
7588 js_cur_has_key = cin_has_js_key(theline);
7589
7538 /* 7590 /*
7539 * if we're looking at a closing brace, that's where 7591 * If we're looking at a closing brace, that's where
7540 * we want to be. otherwise, add the amount of room 7592 * we want to be. otherwise, add the amount of room
7541 * that an indent is supposed to be. 7593 * that an indent is supposed to be.
7542 */ 7594 */
7543 if (theline[0] == '}') 7595 if (theline[0] == '}')
7544 { 7596 {
7641 7693
7642 /* 7694 /*
7643 * Search backwards. If we find something we recognize, line up 7695 * Search backwards. If we find something we recognize, line up
7644 * with that. 7696 * with that.
7645 * 7697 *
7646 * if we're looking at an open brace, indent 7698 * If we're looking at an open brace, indent
7647 * the usual amount relative to the conditional 7699 * the usual amount relative to the conditional
7648 * that opens the block. 7700 * that opens the block.
7649 */ 7701 */
7650 curwin->w_cursor = cur_curpos; 7702 curwin->w_cursor = cur_curpos;
7651 for (;;) 7703 for (;;)
8049 * initialisation (not indented) or a variable declaration 8101 * initialisation (not indented) or a variable declaration
8050 * (indented). 8102 * (indented).
8051 */ 8103 */
8052 terminated = cin_isterminated(l, FALSE, TRUE); 8104 terminated = cin_isterminated(l, FALSE, TRUE);
8053 8105
8106 if (js_cur_has_key)
8107 {
8108 js_cur_has_key = 0; /* only check the first line */
8109 if (curbuf->b_ind_js && terminated == ',')
8110 {
8111 /* For Javascript we might be inside an object:
8112 * key: something, <- align with this
8113 * key: something
8114 * or:
8115 * key: something + <- align with this
8116 * something,
8117 * key: something
8118 */
8119 lookfor = LOOKFOR_JS_KEY;
8120 }
8121 }
8122 if (lookfor == LOOKFOR_JS_KEY && cin_has_js_key(l))
8123 {
8124 amount = get_indent();
8125 break;
8126 }
8127 if (lookfor == LOOKFOR_NO_COMMA)
8128 {
8129 if (terminated != ',')
8130 /* line below current line is the one that starts a
8131 * (possibly broken) line ending in a comma. */
8132 break;
8133 amount = get_indent();
8134 if (curwin->w_cursor.lnum - 1 == ourscope)
8135 /* line above is start of the scope, thus current line
8136 * is the one that stars a (possibly broken) line
8137 * ending in a comma. */
8138 break;
8139 }
8140
8054 if (terminated == 0 || (lookfor != LOOKFOR_UNTERM 8141 if (terminated == 0 || (lookfor != LOOKFOR_UNTERM
8055 && terminated == ',')) 8142 && terminated == ','))
8056 { 8143 {
8057 /* 8144 /*
8058 * if we're in the middle of a paren thing, 8145 * if we're in the middle of a paren thing,
8060 * we can get the right prevailing indent 8147 * we can get the right prevailing indent
8061 * if ( foo && 8148 * if ( foo &&
8062 * bar ) 8149 * bar )
8063 */ 8150 */
8064 /* 8151 /*
8065 * position the cursor over the rightmost paren, so that 8152 * Position the cursor over the rightmost paren, so that
8066 * matching it will take us back to the start of the line. 8153 * matching it will take us back to the start of the line.
8154 * Ignore a match before the start of the block.
8067 */ 8155 */
8068 (void)find_last_paren(l, '(', ')'); 8156 (void)find_last_paren(l, '(', ')');
8069 trypos = find_match_paren(corr_ind_maxparen(&cur_curpos)); 8157 trypos = find_match_paren(corr_ind_maxparen(&cur_curpos));
8158 if (trypos != NULL && (trypos->lnum < tryposBrace->lnum
8159 || (trypos->lnum == tryposBrace->lnum
8160 && trypos->col < tryposBrace->col)))
8161 trypos = NULL;
8070 8162
8071 /* 8163 /*
8072 * If we are looking for ',', we also look for matching 8164 * If we are looking for ',', we also look for matching
8073 * braces. 8165 * braces.
8074 */ 8166 */
8115 8207
8116 /* 8208 /*
8117 * Get indent and pointer to text for current line, 8209 * Get indent and pointer to text for current line,
8118 * ignoring any jump label. XXX 8210 * ignoring any jump label. XXX
8119 */ 8211 */
8120 if (!curbuf->b_ind_js) 8212 if (curbuf->b_ind_js)
8213 cur_amount = get_indent();
8214 else
8121 cur_amount = skip_label(curwin->w_cursor.lnum, &l); 8215 cur_amount = skip_label(curwin->w_cursor.lnum, &l);
8122 else
8123 cur_amount = get_indent();
8124 /* 8216 /*
8125 * If this is just above the line we are indenting, and it 8217 * If this is just above the line we are indenting, and it
8126 * starts with a '{', line it up with this line. 8218 * starts with a '{', line it up with this line.
8127 * while (not) 8219 * while (not)
8128 * -> { 8220 * -> {
8140 * -> { 3, 4 } 8232 * -> { 3, 4 }
8141 */ 8233 */
8142 if (*skipwhite(l) != '{') 8234 if (*skipwhite(l) != '{')
8143 amount += curbuf->b_ind_open_extra; 8235 amount += curbuf->b_ind_open_extra;
8144 8236
8145 if (curbuf->b_ind_cpp_baseclass) 8237 if (curbuf->b_ind_cpp_baseclass && !curbuf->b_ind_js)
8146 { 8238 {
8147 /* have to look back, whether it is a cpp base 8239 /* have to look back, whether it is a cpp base
8148 * class declaration or initialization */ 8240 * class declaration or initialization */
8149 lookfor = LOOKFOR_CPP_BASECLASS; 8241 lookfor = LOOKFOR_CPP_BASECLASS;
8150 continue; 8242 continue;
8300 * but only, of no other statement has been found 8392 * but only, of no other statement has been found
8301 * yet. 8393 * yet.
8302 */ 8394 */
8303 if (lookfor == LOOKFOR_INITIAL && terminated == ',') 8395 if (lookfor == LOOKFOR_INITIAL && terminated == ',')
8304 { 8396 {
8305 lookfor = LOOKFOR_ENUM_OR_INIT; 8397 if (curbuf->b_ind_js)
8306 cont_amount = cin_first_id_amount(); 8398 {
8399 /* Search for a line ending in a comma
8400 * and line up with the line below it
8401 * (could be the current line).
8402 * some = [
8403 * 1, <- line up here
8404 * 2,
8405 * some = [
8406 * 3 + <- line up here
8407 * 4 *
8408 * 5,
8409 * 6,
8410 */
8411 lookfor = LOOKFOR_NO_COMMA;
8412 amount = get_indent(); /* XXX */
8413 trypos = find_match_char('[',
8414 curbuf->b_ind_maxparen);
8415 if (trypos != NULL)
8416 {
8417 if (trypos->lnum
8418 == curwin->w_cursor.lnum - 1)
8419 {
8420 /* Current line is first inside
8421 * [], line up with it. */
8422 break;
8423 }
8424 ourscope = trypos->lnum;
8425 }
8426 }
8427 else
8428 {
8429 lookfor = LOOKFOR_ENUM_OR_INIT;
8430 cont_amount = cin_first_id_amount();
8431 }
8307 } 8432 }
8308 else 8433 else
8309 { 8434 {
8310 if (lookfor == LOOKFOR_INITIAL 8435 if (lookfor == LOOKFOR_INITIAL
8311 && *l != NUL 8436 && *l != NUL
8312 && l[STRLEN(l) - 1] == '\\') 8437 && l[STRLEN(l) - 1] == '\\')
8313 /* XXX */ 8438 /* XXX */
8314 cont_amount = cin_get_equal_amount( 8439 cont_amount = cin_get_equal_amount(
8315 curwin->w_cursor.lnum); 8440 curwin->w_cursor.lnum);
8316 if (lookfor != LOOKFOR_TERM) 8441 if (lookfor != LOOKFOR_TERM
8442 && lookfor != LOOKFOR_JS_KEY)
8317 lookfor = LOOKFOR_UNTERM; 8443 lookfor = LOOKFOR_UNTERM;
8318 } 8444 }
8319 } 8445 }
8320 } 8446 }
8321 } 8447 }
8322 8448
8323 /* 8449 /*
8324 * Check if we are after a while (cond); 8450 * Check if we are after a while (cond);
8325 * If so: Ignore until the matching "do". 8451 * If so: Ignore until the matching "do".
8326 */ 8452 */
8327 /* XXX */ 8453 else if (cin_iswhileofdo_end(terminated)) /* XXX */
8328 else if (cin_iswhileofdo_end(terminated))
8329 { 8454 {
8330 /* 8455 /*
8331 * Found an unterminated line after a while ();, line up 8456 * Found an unterminated line after a while ();, line up
8332 * with the last one. 8457 * with the last one.
8333 * while (cond); 8458 * while (cond);
8536 8661
8537 /* subtract extra left-shift for jump labels */ 8662 /* subtract extra left-shift for jump labels */
8538 if (curbuf->b_ind_jump_label > 0 && original_line_islabel) 8663 if (curbuf->b_ind_jump_label > 0 && original_line_islabel)
8539 amount -= curbuf->b_ind_jump_label; 8664 amount -= curbuf->b_ind_jump_label;
8540 } 8665 }
8541
8542 /*
8543 * ok -- we're not inside any sort of structure at all!
8544 *
8545 * this means we're at the top level, and everything should
8546 * basically just match where the previous line is, except
8547 * for the lines immediately following a function declaration,
8548 * which are K&R-style parameters and need to be indented.
8549 */
8550 else 8666 else
8551 { 8667 {
8552 /* 8668 /*
8669 * ok -- we're not inside any sort of structure at all!
8670 *
8671 * This means we're at the top level, and everything should
8672 * basically just match where the previous line is, except
8673 * for the lines immediately following a function declaration,
8674 * which are K&R-style parameters and need to be indented.
8675 *
8553 * if our line starts with an open brace, forget about any 8676 * if our line starts with an open brace, forget about any
8554 * prevailing indent and make sure it looks like the start 8677 * prevailing indent and make sure it looks like the start
8555 * of a function 8678 * of a function
8556 */ 8679 */
8557 8680
8696 * char *string_array[] = { "foo", 8819 * char *string_array[] = { "foo",
8697 * / * x * / "b};ar" }; / * foobar * / 8820 * / * x * / "b};ar" }; / * foobar * /
8698 */ 8821 */
8699 if (cin_ends_in(l, (char_u *)"};", NULL)) 8822 if (cin_ends_in(l, (char_u *)"};", NULL))
8700 break; 8823 break;
8824
8825 /*
8826 * If the previous line ends on '[' we are probably in an
8827 * array constant:
8828 * something = [
8829 * 234, <- extra indent
8830 */
8831 if (cin_ends_in(l, (char_u *)"[", NULL))
8832 {
8833 amount = get_indent() + ind_continuation;
8834 break;
8835 }
8701 8836
8702 /* 8837 /*
8703 * Find a line only has a semicolon that belongs to a previous 8838 * Find a line only has a semicolon that belongs to a previous
8704 * line ending in '}', e.g. before an #endif. Don't increase 8839 * line ending in '}', e.g. before an #endif. Don't increase
8705 * indent then. 8840 * indent then.