Mercurial > hg > xemacs-beta
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 |