Elisp'de bir dize derin kopyalansın mı?


9

Düzgünleştirilmiş bir dizem var. Orijinal dize özelliklerini korurken daha fazla özellik eklemek için bunun derin bir kopyasını yapmak istiyorum. Bunu nasıl kolayca yapabilirim?

Misal

Tek tek değerlendirin:

(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)

Ve sonuç:

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
Bunu bir hata olarak rapor ederdim add-face-text-property. Bu liste başkaları tarafından belirtildiğinde başarısız olduğu için listeyi yıkıcı bir şekilde değiştirmemelidir.
Lindydancer


Hatayı bildirdiğiniz için teşekkür ederiz. Çok kötü kimse henüz yanıt vermedi. Bu yardımcı fonksiyonun (C kodlu) düzeltilmesini sağlamak iyi olur.
Drew

Yanıtlar:


7

font-lock-append-text-propertyText özelliğini eklemek için işlevi kullanabilirsiniz . Değeri yıkıcı bir şekilde değiştirmez.

Örneğin:

(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)))

Burada, test-str-1orijinal değerini korudu.


4

Bunu metin özellikleri üzerinde yineleyerek, alttaki özellik verilerini kopyalayarak ve mevcut özelliklerin üzerine yeni kopyalar yazarak yapabileceğinizi buldum.

(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)))

Testlerimde, bu readçözümünüzden yaklaşık% 20 daha hızlıydı . Ayrıca bir geçici arabellek kullanmayan ve daha az kod olan ancak daha yavaş olan bir dizenin özelliklerini değiştiren bir sürüm yazdım.

C koduna bakıldığında, liste yapısını yeniden oluşturacak ancak öğeleri değere göre kopyalamayacak olan copy_sequence ile özellik plistlerini kopyalar, böylece örneğinizde liste değeri olan yüz gibi özellikler başvuru ile kopyalanır ve değiştirilir. Böcek ya da değil, bilmiyorum


2

Kullanabilirsiniz (concat the-original-string).

Örneğin:

(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
Çalışmıyor, bir örnek ekleyeceğim.
abo-abo

1
Hile, yaptığım gibi özelliklerde iç içe bir liste olması. O zaman concatişe yaramaz.
abo-abo

@ Abo-Abo. Tamam, şimdi anlıyorum. Eklediğiniz örnekte bunu fark etmedim. Bu durumda cevabım yok, ama bence böyle bir işleve gerçek bir ihtiyaç var. (Potansiyel bir sorun, bilinmeyen bir mülkün bir tür paylaşılan nesneye atıfta bulunmayı
bekleyip bekleyemeyeceğini bilmenin imkansız olmasıdır

1

(Çok etkili olmayan) bir çözüm bulundu:

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

2
Proprties #karakteri içeriyorsa geçici çözüm başarısız olur .
abo-abo

# karakterinin sembol adının bir parçası olup olmadığı anlamına mı geliyor? Veya arabellekler veya yazdırılamayan diğer veriler anlamına gelen ortalama özellikler mi? Birincisi, bir hata dosyalamalısınız.
Malabarba

özelliklerindeki tamponlar
abo-abo
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.