comparison src/search.c @ 4199:3660d327399f

[xemacs-hg @ 2007-10-01 08:07:39 by stephent] Implement subexpression replacement in replace-match. <87ejgf6yy9.fsf@uwakimon.sk.tsukuba.ac.jp>
author stephent
date Mon, 01 Oct 2007 08:07:57 +0000
parents 3d8143fc88e1
children f70e56bb52a7
comparison
equal deleted inserted replaced
4198:fb83e69ce80a 4199:3660d327399f
2362 return Qnil; 2362 return Qnil;
2363 } 2363 }
2364 2364
2365 DEFUN ("replace-match", Freplace_match, 1, 5, 0, /* 2365 DEFUN ("replace-match", Freplace_match, 1, 5, 0, /*
2366 Replace text matched by last search with REPLACEMENT. 2366 Replace text matched by last search with REPLACEMENT.
2367 If second arg FIXEDCASE is non-nil, do not alter case of replacement text. 2367 Leaves point at end of replacement text.
2368 Optional boolean FIXEDCASE inhibits matching case of REPLACEMENT to source.
2369 Optional boolean LITERAL inhibits interpretation of escape sequences.
2370 Optional STRING provides the source text to replace.
2371 Optional STRBUFFER may be a buffer, providing match context, or an integer
2372 specifying the subexpression to replace.
2373
2374 If FIXEDCASE is non-nil, do not alter case of replacement text.
2368 Otherwise maybe capitalize the whole text, or maybe just word initials, 2375 Otherwise maybe capitalize the whole text, or maybe just word initials,
2369 based on the replaced text. 2376 based on the replaced text.
2370 If the replaced text has only capital letters 2377 If the replaced text has only capital letters and has at least one
2371 and has at least one multiletter word, convert REPLACEMENT to all caps. 2378 multiletter word, convert REPLACEMENT to all caps.
2372 If the replaced text has at least one word starting with a capital letter, 2379 If the replaced text has at least one word starting with a capital letter,
2373 then capitalize each word in REPLACEMENT. 2380 then capitalize each word in REPLACEMENT.
2374 2381
2375 If third arg LITERAL is non-nil, insert REPLACEMENT literally. 2382 If LITERAL is non-nil, insert REPLACEMENT literally.
2376 Otherwise treat `\\' as special: 2383 Otherwise treat `\\' as special:
2377 `\\&' in REPLACEMENT means substitute original matched text. 2384 `\\&' in REPLACEMENT means substitute original matched text.
2378 `\\N' means substitute what matched the Nth `\\(...\\)'. 2385 `\\N' means substitute what matched the Nth `\\(...\\)'.
2379 If Nth parens didn't match, substitute nothing. 2386 If Nth parens didn't match, substitute nothing.
2380 `\\\\' means insert one `\\'. 2387 `\\\\' means insert one `\\'.
2383 `\\U' means begin upcasing all following characters. 2390 `\\U' means begin upcasing all following characters.
2384 `\\L' means begin downcasing all following characters. 2391 `\\L' means begin downcasing all following characters.
2385 `\\E' means terminate the effect of any `\\U' or `\\L'. 2392 `\\E' means terminate the effect of any `\\U' or `\\L'.
2386 Case changes made with `\\u', `\\l', `\\U', and `\\L' override 2393 Case changes made with `\\u', `\\l', `\\U', and `\\L' override
2387 all other case changes that may be made in the replaced text. 2394 all other case changes that may be made in the replaced text.
2388 FIXEDCASE and LITERAL are optional arguments. 2395
2389 Leaves point at end of replacement text. 2396 If non-nil, STRING is the source string, and a new string with the specified
2390 2397 replacements is created and returned. Otherwise the current buffer is the
2391 The optional fourth argument STRING can be a string to modify. 2398 source text.
2392 In that case, this function creates and returns a new string 2399
2393 which is made by replacing the part of STRING that was matched. 2400 If non-nil, STRBUFFER may be an integer, interpreted as the index of the
2394 When fourth argument is a string, fifth argument STRBUFFER specifies 2401 subexpression to replace in the source text, or a buffer to provide the
2395 the buffer to be used for syntax-table and case-table lookup and 2402 syntax table and case table. If nil, then the \"subexpression\" is 0, i.e.,
2396 defaults to the current buffer. When fourth argument is not a string, 2403 the whole match, and the current buffer provides the syntax and case tables.
2397 the buffer that the match occurred in has automatically been remembered 2404 If STRING is nil, STRBUFFER must be nil or an integer.
2398 and you do not need to specify it. 2405
2399 2406 Specifying a subexpression is only useful after a regular expression match,
2400 When fourth argument is nil, STRBUFFER specifies a subexpression of 2407 since a fixed string search has no non-trivial subexpressions.
2401 the match. It says to replace just that subexpression instead of the 2408
2402 whole match. This is useful only after a regular expression search or 2409 It is not possible to specify both a buffer and a subexpression. If that is
2403 match since only regular expressions have distinguished subexpressions. 2410 desired, the idiom `(with-current-buffer BUFFER (replace-match ... INTEGER))'
2404 2411 may be appropriate.
2405 If no match (including searches) has been conducted or the requested 2412
2413 If STRING is nil but the last thing matched (or searched) was a string, or
2414 STRING is a string but the last thing matched was a buffer, an
2415 `invalid-argument' error will be signaled. (XEmacs does not check that the
2416 last thing searched is the source string, but it is not useful to use a
2417 different string as source.)
2418
2419 If no match (including searches) has been successful or the requested
2406 subexpression was not matched, an `args-out-of-range' error will be 2420 subexpression was not matched, an `args-out-of-range' error will be
2407 signaled. (If no match has ever been conducted in this instance of 2421 signaled. (If no match has ever been conducted in this instance of
2408 XEmacs, an `invalid-operation' error will be signaled. This is very 2422 XEmacs, an `invalid-operation' error will be signaled. This is very
2409 rare.) 2423 rare.)
2410 */ 2424 */
2428 int sub = 0; 2442 int sub = 0;
2429 int speccount; 2443 int speccount;
2430 2444
2431 CHECK_STRING (replacement); 2445 CHECK_STRING (replacement);
2432 2446
2447 /* Because GNU decided to be incompatible here, we support the following
2448 baroque and bogus API for the STRING and STRBUFFER arguments:
2449 types interpretations
2450 STRING STRBUFFER STRING STRBUFFER
2451 nil nil none 0 = index of subexpression to replace
2452 nil integer none index of subexpression to replace
2453 nil other ***** error *****
2454 string nil source current buffer provides syntax table
2455 subexpression = 0 (whole match)
2456 string buffer source buffer providing syntax table
2457 subexpression = 0 (whole match)
2458 string integer source current buffer provides syntax table
2459 subexpression = STRBUFFER
2460 string other ***** error *****
2461 */
2462
2463 /* Do STRBUFFER first; if STRING is nil, we'll overwrite BUF and BUFFER. */
2464
2465 /* If the match data were abstracted into a special "match data" type
2466 instead of the typical half-assed "let the implementation be visible"
2467 form it's in, we could extend it to include the last string matched
2468 and the buffer used for that matching. But of course we can't change
2469 it as it is.
2470 */
2471 if (NILP (strbuffer) || BUFFERP (strbuffer))
2472 {
2473 buf = decode_buffer (strbuffer, 0);
2474 }
2475 else if (!NILP (strbuffer))
2476 {
2477 CHECK_INT (strbuffer);
2478 sub = XINT (strbuffer);
2479 if (sub < 0 || sub >= (int) search_regs.num_regs)
2480 invalid_argument ("match data register invalid", strbuffer);
2481 if (search_regs.start[sub] < 0)
2482 invalid_argument ("match data register not set", strbuffer);
2483 buf = current_buffer;
2484 }
2485 else
2486 invalid_argument ("STRBUFFER must be nil, a buffer, or an integer",
2487 strbuffer);
2488 buffer = wrap_buffer (buf);
2489
2433 if (! NILP (string)) 2490 if (! NILP (string))
2434 { 2491 {
2435 CHECK_STRING (string); 2492 CHECK_STRING (string);
2436 if (!EQ (last_thing_searched, Qt)) 2493 if (!EQ (last_thing_searched, Qt))
2437 invalid_argument ("last thing matched was not a string", Qunbound); 2494 invalid_argument ("last thing matched was not a string", Qunbound);
2438 /* If the match data
2439 were abstracted into a special "match data" type instead
2440 of the typical half-assed "let the implementation be
2441 visible" form it's in, we could extend it to include
2442 the last string matched and the buffer used for that
2443 matching. But of course we can't change it as it is. */
2444 buf = decode_buffer (strbuffer, 0);
2445 buffer = wrap_buffer (buf);
2446 } 2495 }
2447 else 2496 else
2448 { 2497 {
2449 if (!NILP (strbuffer))
2450 {
2451 CHECK_INT (strbuffer);
2452 sub = XINT (strbuffer);
2453 if (sub < 0 || sub >= (int) search_regs.num_regs)
2454 args_out_of_range (strbuffer, make_int (search_regs.num_regs));
2455 }
2456 if (!BUFFERP (last_thing_searched)) 2498 if (!BUFFERP (last_thing_searched))
2457 invalid_argument ("last thing matched was not a buffer", Qunbound); 2499 invalid_argument ("last thing matched was not a buffer", Qunbound);
2458 buffer = last_thing_searched; 2500 buffer = last_thing_searched;
2459 buf = XBUFFER (buffer); 2501 buf = XBUFFER (buffer);
2460 } 2502 }
2461 2503
2462 syntax_table = buf->mirror_syntax_table; 2504 syntax_table = buf->mirror_syntax_table;
2555 if (!NILP (string)) 2597 if (!NILP (string))
2556 { 2598 {
2557 Lisp_Object before, after; 2599 Lisp_Object before, after;
2558 2600
2559 speccount = specpdl_depth (); 2601 speccount = specpdl_depth ();
2560 before = Fsubstring (string, Qzero, make_int (search_regs.start[0])); 2602 before = Fsubstring (string, Qzero, make_int (search_regs.start[sub]));
2561 after = Fsubstring (string, make_int (search_regs.end[0]), Qnil); 2603 after = Fsubstring (string, make_int (search_regs.end[sub]), Qnil);
2562 2604
2563 /* Do case substitution into REPLACEMENT if desired. */ 2605 /* Do case substitution into REPLACEMENT if desired. */
2564 if (NILP (literal)) 2606 if (NILP (literal))
2565 { 2607 {
2566 Charcount stlen = string_char_length (replacement); 2608 Charcount stlen = string_char_length (replacement);
2598 { 2640 {
2599 literal_end = strpos - 1; 2641 literal_end = strpos - 1;
2600 substart = search_regs.start[0]; 2642 substart = search_regs.start[0];
2601 subend = search_regs.end[0]; 2643 subend = search_regs.end[0];
2602 } 2644 }
2645 /* #### This logic is totally broken,
2646 since we can have backrefs like "\99", right? */
2603 else if (c >= '1' && c <= '9' && 2647 else if (c >= '1' && c <= '9' &&
2604 c <= search_regs.num_regs + '0') 2648 c <= search_regs.num_regs + '0')
2605 { 2649 {
2606 if (search_regs.start[c - '0'] >= 0) 2650 if (search_regs.start[c - '0'] >= 0)
2607 { 2651 {
2757 if (c == '&') 2801 if (c == '&')
2758 Finsert_buffer_substring 2802 Finsert_buffer_substring
2759 (buffer, 2803 (buffer,
2760 make_int (search_regs.start[0] + offset), 2804 make_int (search_regs.start[0] + offset),
2761 make_int (search_regs.end[0] + offset)); 2805 make_int (search_regs.end[0] + offset));
2806 /* #### This logic is totally broken,
2807 since we can have backrefs like "\99", right? */
2762 else if (c >= '1' && c <= '9' && 2808 else if (c >= '1' && c <= '9' &&
2763 c <= search_regs.num_regs + '0') 2809 c <= search_regs.num_regs + '0')
2764 { 2810 {
2765 if (search_regs.start[c - '0'] >= 1) 2811 if (search_regs.start[c - '0'] >= 1)
2766 Finsert_buffer_substring 2812 Finsert_buffer_substring