Ganti teks di dalam berbagai pembatas (mis: kurung, tanda kutip)

9

Saya sering melakukan implementasi pengujian dengan nilai-nilai hardcoded yang kemudian ingin saya ubah. Suka

ref = open('specific-file-name')

Yang ingin saya ubah menjadi

ref = open(fname)

Saya sudah terbiasa vim dan di sana saya bisa mengetik ci(fnamedengan asumsi titik itu ada di dalam kurung. ( ci(singkatan menggantikan kurung bagian dalam).

Bagaimana saya bisa mencapai sesuatu seperti 'ganti batin' di emacs?

kain88
sumber

Jawaban:

9

Menggunakan expand-region

Saya akan merekomendasikan menginstal expand-regionpaket (tersedia di Melpa juga). Ini akan berguna untuk mengedit situasi yang disebutkan dalam contoh Anda dan banyak lagi.

expand-regioncerdas. Berdasarkan mode utama, ini akan mencoba mencari tahu apa yang Anda coba pilih. Saya tidak tahu dari bahasa mana Anda memiliki cuplikan contoh jadi saya akan menggunakan cuplikan kode contoh Anda dan sedikit memodifikasinya untuk Python (hapus;). Jadi penjelasan saya di bawah ini adalah dengan potongan kode di bawah ini dalam python-modebuffer.

ref = open('specific-file-name') 

Jika titik di sebelah satu kutipan

Kotak hitam vertikal di bawah ini menunjukkan bagaimana kursor akan terlihat.

# point on left of left quote, the cursor is hiding the quote under it
ref = open(▮specific-file-name') 

# point on left of right parenthesis, the cursor is hiding the parenthesis under it       
ref = open('specific-file-name'▮

Dalam kedua kasus, ketika Anda melakukannya M-x er/expand-region, 'specific-file-name'akan dipilih dan Anda kemudian dapat menekan DEL(atau backspace) untuk menghapus pilihan.

Jika Anda telah delete-selection-modemengaktifkan (Saya ingin itu diaktifkan secara pribadi), Anda dapat mulai mengetik setelah melakukan seleksi dan itu akan menimpa seleksi.

Tentu saja, jika Anda menggunakan er/expand-regionbanyak, Anda akan mengikatnya dengan kunci pendek yang mengikat. Saya suka mengikatnya C-\. Jadi dengan poin di sebelah satu kutipan: C-\fnameakan memberi sayaref = open(fname);

masukkan deskripsi gambar di sini

Jika titik ada di suatu tempat di dalam tanda kutip

Menggunakan expand-region, intinya tidak perlu dekat dengan tanda kutip. Tetapi dalam kasus ini, Anda hanya perlu beberapa stroke kunci (biasanya satu atau dua lagi).

Katakanlah posisi kursor seperti di bawah sekarang:

# cursor shown below is hiding the i character under it
ref = open('specif▮c-file-name')

Menggunakan ikatan yang sama seperti yang saya gunakan di atas:

  • Pertama kali saya menekan C-\akan memilih specific.
  • Sekarang saya hanya perlu menekan \untuk memperluas pemilihan ( expand-regionfitur). Itu akan memilih specific-file-name.

    Jika Anda telah terikat er/expand-regionuntuk C-=, memukul =lagi akan melakukan ekspansi tambahan. Baca dokumentasinya tentang cara mengikat kunci untuk penambahan / kontraksi seleksi secara bertahap.

  • Memukul \sekali lagi akan memilih 'specific-file-name'.
  • Sekarang Anda melanjutkan dengan menekan DELuntuk menghapus pilihan dan kemudian ketik fname. Jika delete-selection-modediaktifkan, Anda dapat melewati DELstroke.

Singkatnya, dengan delete-selection-modediaktifkan, stroke kunci seperti: C-\\\fname.

masukkan deskripsi gambar di sini


Menggunakan change-inner

Saya juga menemukan change-innerpaket oleh expand-regionpenulis utama (yang digunakan expand-regionsebagai back-end) untuk melakukan persis apa yang dilakukan Vim ci(dan juga mengubah bagian luar ).

Dari paket README:

change-innermemberi Anda ciperintah vim , membangun expand-region. Ini paling mudah dijelaskan dengan contoh:

function test() {
  return "semantic kill";
}

Dengan titik setelah kata semantik

change-inner "akan membunuh isi string
change-outer "akan membunuh seluruh string
change-inner {akan membunuh pernyataan-kembali
change-outer {akan membunuh seluruh blok

Kaushal Modi
sumber
3

Dengan suatu daerah

Untuk melakukan ini dengan suatu wilayah, mulai dari:

ref = open(|'specific-file-name');

tekan C-SPC C-b C-M-n C-b C-w.

Cara lebih cepat

Mulai dari titik sebelum paren, seperti di Vim:

ref = open|('specific-file-name');

C-M-k( kill-sexp) akan menghasilkan:

ref = open|;

Jika sudah electric-pair-modeaktif, Anda dapat memasukkan kembali ()dengan hanya (. Jadi urutan kunci lengkap C-M-k (- tidak lebih lama dari ci(.

abo-abo
sumber
1
Juga, jika intinya adalah sebelum kutipan kiri ref = open(|'specific-file-name');,, C-M-kakan memberi ref = open(|);. Kutipan juga sexps seimbang .
Kaushal Modi
Saya sedang memikirkan delete-everything-inside-parenshal semacam itu, bukan delete-first-sexp-inside-parens.
abo-abo
Solusi yang bagus tetapi mengharuskan saya untuk pindah titik sebelum ekspresi yang ingin saya ganti. Paket 'change inner' berfungsi ketika titik berada di mana saja di dalam ekspresi (sama dengan vi).
kain88
1

evil mengemulasi sebagian besar Vim, dan itu objek teks keluar dari kotak.

Dengan kata lain, dengan evildiaktifkan dan menggunakan ikatan kunci default, ci(akan melakukan persis apa yang Anda minta: ubah apa yang ada di dalam tanda kurung terlampir.

Lebih tepatnya, ci(akan berantai evil-changeke evil-inner-paren. Anda juga dapat membuat objek teks sewenang-wenang sendiri sesuka Anda.

Dan
sumber
Saya tahu tentang kejahatan (saya sudah menggunakannya untuk sementara waktu sekarang). Saya ingin tahu bagaimana ini dapat dilakukan di emacs 'murni'.
kain88
@ kain88: cukup adil: Saya kira akan ada beberapa jawaban untuk pertanyaan ini. Karena penasaran, jika Anda sudah menggunakan evil, mengapa Anda menginginkan yang bukan evilalternatif?
Dan
(komentar tidak serius) @Dan Dia mungkin bersiap untuk datang ke sisi gelap.
Kaushal Modi
Saya perhatikan bahwa kejahatan terkadang tidak cocok dengan mode lain. Ditambah lagi, saya ingin tahu bagaimana pengeditan hanya menggunakan emacs
kain88
1

Menggunakan smartparens

Membunuh

1) Gunakan C-M-u( sp-backward-up-sexp) untuk keluar dari 'pembatas.

2) Gunakan C-0 C-M-k( 0awalan + sp-kill-sexp) untuk membunuh hal-hal di dalam sexp saat ini atau C-k( sp-kill-hybrid-sexp). Yang terakhir hanya berfungsi ketika smartparens-strict-modediaktifkan dan sexp saat ini cocok dalam satu baris.

ref = open('specific|-file-name')
// C-M-u
ref = open(|'specific-file-name')
// C-k
ref = open(|)

Tandai dan hapus / bunuh / salin

1) Temukan jalan Anda ke awal sexp (dalam contoh ini C-M-u sp-backward-up-sexpsudah cukup), tetapkan tanda C-SPCdan pergi ke akhir sexp dengan sp-end-of-sexp.

2) Kemudian Anda dapat melakukan apa pun yang Anda inginkan: C-wuntuk membunuh wilayah, M-wuntuk membunuh-ring-save (menyalin) wilayah, backspacemenghapusnya tanpa mengacaukan cincin pembunuhan (hanya dengan delete-selection-mode)

ref = open('specific|-file-name')
// C-M-u
ref = open(|'specific-file-name')
// C-SPC - mark is now active
ref = open(|'specific-file-name')
// sp-end-of-sexp (my binding: M-e)
ref = open(<'specific-file-name'|)
// backspace
ref = open(|)

Fungsi mark-inside-sexp

smartparensPaket memiliki sp-mark-sexpfungsi yang menandai seluruh sexp berikutnya, yaitu pembatas dan hal-hal di antara mereka.

Anda bisa menggunakan fungsi seperti ini untuk membuang pembatas dari pilihan:

(defun mark-inside-sexp-using-sp ()
  (interactive)
  (sp-mark-sexp)
  (exchange-point-and-mark) (backward-char)
  (exchange-point-and-mark) (forward-char)
  (message "MARK INSIDE SEXP (using sp)"))

(global-set-key (kbd "s-SPC") 'mark-inside-sexp-using-sp)
;; this is "super" modifier (win key) with space

Keluar dari sexp Anda menggunakan C-M-uberulang kali dan tandai mark-inside-sexp-using-sp dan kemudian memutuskan apa yang harus dilakukan dengan wilayah aktif.

mmajcher
sumber