Elisp에서 문자열을 딥 카피합니까?


9

적절한 문자열이 있습니다. 원래 문자열의 속성을 유지하면서 더 많은 속성을 추가하기 위해 딥 카피를 만들고 싶습니다. 어떻게하면 쉽게 할 수 있습니까?

하나씩 평가 :

(setq test-str-1
      #(";; This `is' a test"
        0 3 (fontified nil face font-lock-comment-delimiter-face)
        3 9 (fontified nil face font-lock-comment-face)
        9 11 (fontified nil face (font-lock-constant-face font-lock-comment-face))
        11 19 (fontified nil face font-lock-comment-face)))
(setq test-str-2 (concat test-str-1))
(add-face-text-property 0 (length test-str-2) 'foobar t test-str-2)

그리고 결과 :

test-str-2
;; =>
#(";; This `is' a test" 0 3 (fontified nil face (font-lock-comment-delimiter-face foobar))
  3 9 (fontified nil face (font-lock-comment-face foobar))
  9 11 (fontified nil face (font-lock-constant-face font-lock-comment-face foobar))
  11 19 (fontified nil face (font-lock-comment-face foobar)))
test-str-1
;; =>
#(";; This `is' a test" 0 3 (face font-lock-comment-delimiter-face fontified nil)
  3 9 (face font-lock-comment-face fontified nil)
  9 11 (face (font-lock-constant-face font-lock-comment-face foobar) ; <= foobar is here
        fontified nil)
  11 19 (face font-lock-comment-face fontified nil))

2
이 버그를에 버그로 신고합니다 add-face-text-property. 다른 사람들이 해당 목록을 참조 할 때 실패하므로 목록을 파괴적으로 수정해서는 안됩니다.
Lindydancer 12


버그를보고 해 주셔서 감사합니다. 아직 아무도 응답하지 않았습니다. 이 유틸리티 기능 (C로 코딩)을 고정시키는 것이 좋습니다.
Drew

답변:


7

이 기능 font-lock-append-text-property을 사용하여 텍스트 속성을 추가 할 수 있습니다 . 값을 파괴적으로 수정하지는 않습니다.

예를 들면 다음과 같습니다.

(setq test-str-1
      #(";; This `is' a test"
        0 3 (fontified nil face font-lock-comment-delimiter-face)
        3 9 (fontified nil face font-lock-comment-face)
        9 11 (fontified nil face (font-lock-constant-face font-lock-comment-face))
        11 19 (fontified nil face font-lock-comment-face)))
(setq test-str-2 (concat test-str-1))
(font-lock-append-text-property 0 (length test-str-2) 'face '(foobar t) test-str-2)


test-str-1
#(";; This `is' a test"
  0 3 (face font-lock-comment-delimiter-face fontified nil)
  3 9 (face font-lock-comment-face fontified nil)
  9 11 (face (font-lock-constant-face font-lock-comment-face) fontified nil)
  11 19 (face font-lock-comment-face fontified nil))

test-str-2
#(";; This `is' a test"
  0 3 (fontified nil face (font-lock-comment-delimiter-face foobar t))
  3 9 (fontified nil face (font-lock-comment-face foobar t))
  9 11 (fontified nil face (font-lock-constant-face font-lock-comment-face foobar t))
  11 19 (fontified nil face (font-lock-comment-face foobar t)))

의에서 test-str-1원래 값을 유지했습니다.


4

텍스트 속성을 반복하고 기본 속성 데이터를 복사하고 기존 속성을 새 복사본으로 덮어 써서이 작업을 수행 할 수 있습니다.

(defun deep-copy-text-properties (str)
  (with-temp-buffer
    (insert str)
    (goto-char 1)
    (while (not (eobp))
      (set-text-properties (point)
                           (goto-char (next-char-property-change (point) (point-max)))
                           ;; copy-tree is the important part
                           (copy-tree (text-properties-at (1- (point))))))
    (buffer-string)))

내 테스트에서 이것은 read솔루션 보다 약 20 % 빠릅니다 . 또한 임시 버퍼를 사용하지 않는 코드를 작성하고 코드는 적지 만 속도가 느린 문자열의 속성을 수정했습니다.

C 코드를 보면 목록 구조를 다시 작성하지만 값으로 요소를 복사하지 않는 copy_sequence와 함께 속성 plist를 복사하므로 목록 값이있는 예제의 face와 같은 속성은 참조로 복사되고 수정됩니다. 벌레인지, 모르겠다


2

사용할 수 있습니다 (concat the-original-string).

예를 들면 다음과 같습니다.

(let ((s "TEXT"))
  (set-text-properties 2 3 '(:foreground "blue") s)
  (let ((q (concat s)))
    (add-text-properties 2 3 '(:background "red") q)
    (cons s q)))
;; Returns:
(#("TEXT" 2 3 (:foreground "blue")) . #("TEXT" 2 3 (:foreground "blue" :background "red")))

1
작동하지 않으면 예제를 추가하겠습니다.
abo-abo

1
속임수는 내가하는 것처럼 속성에 중첩 목록을 갖는 것입니다. 그런 다음 concat작동하지 않습니다.
abo-abo

@ abo-abo. 좋아, 이제 봤어 나는 당신의 추가 예제에서 그것을 발견하지 못했습니다. 이 경우 대답이 없지만 그러한 기능이 실제로 필요하다고 생각합니다. (하나의 잠재적 인 문제는 알려지지 않은 속성이 어떤 종류의 공유 ​​객체를 참조 할 수 있는지 알 수 없다는 것입니다.)
Lindydancer

1

(매우 효율적이지 않은) 해결 방법을 찾았습니다.

(setq test-str-2
      (read (prin1-to-string test-str-1)))

2
#속성에 문자가 포함되어 있으면 해결 방법이 실패합니다 .
abo-abo

# 문자가 기호 이름의 일부인지 여부를 의미합니까? 아니면 버퍼 또는 인쇄 할 수없는 기타 데이터 인 속성을 의미합니까? 처음이라면 버그를 신고해야합니다.
Malabarba

속성의 버퍼
abo-abo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.