Bagaimana menemukan dan mengganti Vim tanpa harus mengetik kata aslinya?


53

Saya ingin mengoptimalkan alur kerja "temukan dan ganti" saya di Vim. Itu adalah sesuatu yang sering saya lakukan, karena saya yakin sebagian besar dari Anda juga. Biasanya sesuatu di sepanjang baris - salin blok dan ubah nama variabel di beberapa tempat. Saya tahu, saya tahu, itu mungkin memicu refleks "mengapa Anda menyalin dan menempelkan kode", tapi jangan sampai menyimpang ... Ada banyak kasus penggunaan yang valid :)

Saya sangat menyadari pencarian dan mengganti perintah: :satau :%stetapi saya tidak menyukainya. Itu memaksa saya untuk mengetikkan nama variabel lengkap yang saya cari dan untuk apa saya mengubahnya. Mungkin ada cara yang lebih baik untuk memperbaiki jumlah pengetikan :%s? Saya sering menggunakan nama variabel deskriptif panjang, jadi itu benar-benar pemecah kesepakatan bagi saya. Saya juga tidak suka bagaimana mengetik nama variabel dari awal adalah salah ketik dan dapat menghabiskan waktu dan tenaga otak memburu kesalahan ketik. Saya lebih suka mengetiknya sekali, lalu menyalin dan menempel untuk menghindari ini sepenuhnya jika memungkinkan.

Alur kerja saya saat ini menggunakan beberapa kombinasi gerakan / yank / select / search / put untuk bergerak di sekitar file dan mengganti satu per satu. Itu tidak bagus tetapi memiliki manfaat menghindari mengetikkan nama variabel lengkap. Saya mungkin hanya perlu mengetik beberapa huruf pertama dengan /atau menggunakan perintah gerakan lain (misalnya fx) tergantung pada apa yang ada di sekitar dan kemudian tekan veuntuk memilih seluruh kata. Saya juga tidak keberatan harus mengulangi untuk setiap contoh. Saya tidak pernah melakukan penggantian temuan lengkap tanpa mengonfirmasi setiap perubahan. Tetapi akan jauh lebih disukai jika saya bisa mengulangi tindakan penggantian dengan penekanan tombol tunggal (yang saya tidak bisa lakukan dengan metode ini). setiap penggantian biasanya sesuatu seperti nitu vemaka p(atau bahkan lebih buruk "0p)

Apakah ada cara yang lebih cepat?


1
.mengulangi "blok perintah" terakhir (tidak yakin dengan istilah yang tepat. misalnya: memindahkan + tindakan + teks. untuk contoh: cwtoto<Esc>(ubah dari kursor ke akhir kata dengan "toto"), c/foo<enter>bar<Esc>(ubah dari kursor ke sebelum " foo ", dan ganti dengan" bar "). Anda kemudian dapat memindahkan (dengan kursor, hjkl, atau angka + hjkl (melakukannya n kali), G (pergi ke akhir file), / sesuatu (pergi sebelum" sesuatu "), dll) dan kemudian tekan .untuk mengulangi" blok perintah "yang sama
Olivier Dulac

Saya menggunakan ini sedikit! Namun, itu tidak berfungsi jika Anda ingin menarik sebuah kata dan kemudian mengganti kata lain dengan itu di beberapa tempat. Itulah use case utama yang saya punya masalah, dan terjadi sesuatu seperti n ve "0p. Yang sayangnya tidak dapat ditiru hanya dengan.
Joel

5
n ce ctrl-r 0 <esc> n.n.n.n.n.n.
Kaya

@ Joel, Anda juga dapat merekam makro (qa lalu semua yang Anda inginkan, lalu q: membuat makro a), dan kemudian menggunakan: @a untuk memutar ulang (dan, seperti biasa, 134 @ a untuk melakukannya 134 kali). makro dapat menjadi rumit seperti yang diperlukan (contoh: menemukan sesuatu, pindah ke tempat yang tepat, kemudian ubah kata itu, kemudian pindah ke tempat yang tepat untuk dapat dipanggil lagi di posisi yang lebih baik)
Olivier Dulac

1
Saya telah mempelajari lebih banyak trik VIM yang berguna dari pertanyaan ini daripada dari pertanyaan lain di situs. Terima kasih!
dotancohen

Jawaban:


81

Saya sebenarnya memiliki alur kerja yang sangat mirip dengan milik Anda, (menyalin dan menempelkan blok yang serupa, lalu menggunakan :suntuk mengubah nama variabel) terutama ketika saya sedang menulis banyak baris yang serupa kecuali untuk variabel yang mereka gunakan. Tetapi ada beberapa hal yang saya lakukan yang mungkin berguna bagi Anda.

Hal-hal umum vim

  1. Hal pertama yang akan membantu Anda adalah menyadari bahwa :s//foo/gakan mengisi istilah pencarian apa pun yang Anda gunakan terakhir dan menggantinya dengan foo . Itu saja dapat menghemat banyak waktu, tetapi ketika Anda menggabungkannya dengan perintah asterisk (mencari kata di bawah kursor saat ini) itu menghemat banyak waktu. Misalnya, mengubah semua foomenjadi spam, alih-alih melakukan

    :%s/foo/spam/g
    

    Yang mengharuskan Anda mengetik foo dan spam (yang mungkin merupakan variabel lama), Anda cukup menavigasi ke foo, dan lakukan:

    *:%s//spam/g
    

    Dengan cara ini, Anda dapat dengan cepat mendapatkan nama variabel yang Anda ubah dengan mencarinya, maka Anda tidak perlu mengetiknya. Ini juga akan bekerja dengan baik dengan alur kerja Anda saat ini menggunakan nbanyak. Ini juga bermanfaat untuk digunakan hlsearch, karena Anda dapat secara visual mengetahui di mana variabel yang Anda ganti berada.

    (catatan samping: Perintah tanda bintang akan menambahkan batas kata, yaitu \<dan di \>sekitar kata di bawah kursor. Jika Anda tidak menginginkan ini, gunakan g*saja.)

  2. akan jauh lebih disukai jika saya bisa mengulangi tindakan penggantian dengan sekali menekan tombol

    Anda dapat menggunakan @:untuk mengulang perintah pengganti terakhir. Itu bagus jika Anda ingin melakukan :sperintah pada banyak baris, tetapi tidak semuanya jadi :%stidak akan berfungsi. Pilihan lain adalah bendera konfirmasi, yaitu :%s///gc. Ini akan memungkinkan Anda untuk mengetik yatau npada setiap kejadian untuk memutuskan apakah Anda ingin menggantinya atau tidak.

    Seperti yang ditunjukkan Desty , Anda juga dapat melakukan &untuk menjalankan kembali perintah pengganti terakhir, tetapi perhatikan bahwa ini tidak akan menjaga bendera Anda (seperti globalatau confirm). Apakah itu baik atau buruk tergantung pada pendapat pribadi Anda. Jika Anda ingin menggunakan ini tetapi menyimpannya juga, Anda bisa melakukannya

    nnoremap & :&&<cr>
    
  3. Jika Anda ingin mengubah setiap kemunculan dalam sebuah blok, tetapi tidak setiap kecocokan dalam file, Anda selalu dapat menggunakan pilihan visual dari blok tersebut, yang akan mengisi

    :'<,'>
    

    ke pengganti Anda, yang membatasi ke garis yang telah Anda pilih. Ketika dikombinasikan dengan pendekatan asterisk, saya menemukan ini sangat berguna. Selain itu, jika Anda membuat beberapa perintah pengganti pada blok garis yang sama, Anda dapat menggunakan gvuntuk memilih ulang baris yang sama untuk melakukan perintah lain. (apakah itu :substituteperintah biasa atau biasa saja)

    Jika Anda melakukan perintah pengganti lain, Anda tidak perlu memilih kembali baris yang sama, karena :'<,'> masih akan beroperasi pada baris yang sama. Namun, lebih mudah untuk mengetik

    gv:s
    

    daripada

    :'<,'>s
    

Plugin / Pemetaan yang saya suka

  1. Saya memiliki pemetaan berikut di saya .vimrcyang memperluas pendekatan asterisk sehingga saya hanya perlu mengetik nama yang diinginkan baru:

    "(R)eplace all
    nnoremap <leader>r yiw:%s/\<<C-r>"\>//g<left><left>
    

    Untuk menggunakan ini, cukup letakkan kursor Anda pada kata yang ingin Anda ubah, dan ketik <leader>rNewVarName<cr>dan Anda selesai. Perhatikan bahwa ini akan menggantikan semua kecocokan tanpa memberi Anda opsi untuk mengonfirmasinya, jadi Anda mungkin tidak terlalu menyukainya. Tentu saja, Anda bisa mengubahnya menjadi

    nnoremap <leader>r yiw:%s/\<<C-r>"\>//gc<left><left><left>
    

    Untuk memungkinkan opsi konfirmasi.

    sunting : Mengikuti jawaban Misa dan komentar rcorre , Anda juga dapat menulis ini sebagai

    nnoremap <leader>r :%s/\<<C-r><C-w>\>//g<left><left>
    

    Yang memiliki keuntungan mempertahankan register tanpa nama Anda tetap sama.

  2. Jika Anda mengubah nama grup dari variabel yang sama secara bersamaan, misalnya, berubah

    fooSuffix
    PrefixFoo
    foo1
    SHOUTINGFOO
    

    untuk

    barSuffix
    PrefixBar
    bar1
    SHOUTINGBAR
    

    itu bisa menyusahkan untuk menggantikan mereka semua secara individual. Di sinilah tpope / vim-abolish berguna. Anda dapat mengganti semua ini dalam satu perintah dengan:

    :%S/foo/bar/g
    

    dan itu mengurus kapitalisasi untuk Anda.

Ini seharusnya banyak membantu Anda, tetapi beri tahu saya jika ada sesuatu tentang pendekatan yang tidak Anda sukai atau rasakan ini kurang. Saya senang berbicara tentang lebih banyak pendekatan. :)


Bacaan yang Disarankan:


Oh, saya baru belajar beberapa hal di sini. Bagus! Pendekatan alternatif yang bisa Anda ambil adalah <leader>rc(atau cr) menambahkannya /cdi akhir. Juga, saya telah set gdefaultmenetapkan, karena saya hampir tidak pernah ingin mengganti satu hasil tunggal, jadi itu akan terjadi yiw:%s/\<<C-r>"\>//<left><left>
Wayne Werner

2
Sungguh jawaban yang fantastis!
Scott Lundberg

2
Jika Anda menggunakan ctrl+r-ctrl+wdalam pemetaan (seperti yang disarankan oleh @Mass) itu harus berfungsi sama tetapi tidak akan mengacaukan register yank Anda (yang mungkin atau mungkin tidak diinginkan)
rcorre

1
Satu hal yang perlu diingat ketika bekerja dengan blok teks yang Anda sorot (sebelum memotong / mencabut dll) adalah bahwa Anda dapat memasukkan gv dalam mode normal untuk menyorot kembali teks yang disorot terakhir.

1
Saya telah menulis plugin github.com/hauleth/sad.vim yang berfungsi mirip dengan metode 2. hovewer memungkinkan Anda menggunakan .untuk melakukan penggantian lebih lanjut.
Hauleth

20

The c_CTRL-Rkeluarga peta dapat meningkatkan alur kerja Anda cukup sedikit:

  1. Anda tidak perlu mengetik nama variabel saat menggunakan :s/, cukup gunakan CTRL-R CTRL-Wuntuk memasukkan kata di bawah kursor ke dalam baris perintah (peringatan: ini tidak luput dari karakter khusus, seperti *halnya).

  2. Setelah membuat perubahan kecil menggunakan ce, Anda dapat mencari menggunakan kata lama / CTRL-R -. Kemudian gunakan .untuk mengulangi perubahan.

  3. Jika Anda perlu melakukan perubahan pada pola pencarian CTRL-R /akan menempatkan pencarian yang ada ke dalam baris perintah.

  4. Akhirnya, Anda dapat menggunakan konten register apa pun CTRL-R {register}


Poin bagus! Saya selalu lupa tentang Ctrl R. Saya akan melihat apakah saya bisa melakukannya juga.
Joel

2
Layak disebutkan secara khusus Ctrl-R /? Saya menggunakan ini cukup sering dalam :sperintah jika saya ingin menggunakan istilah pencarian yang hampir tetapi tidak persis sama dengan yang sebelumnya.
Kaya

12

Ada beberapa metode lagi yang (mengejutkan saya!) Belum disebutkan.

Menggunakan gnPerintah

gnberfungsi seperti nperintah, kecuali bahwa selain melompat ke pertandingan, itu memasuki mode visual, dengan seluruh pertandingan dipilih.

Jadi, untuk mengubah kata (atau apa pun yang dapat Anda cocokkan dengan ekspresi reguler!) Pertama cari 1 , lalu tekan cgndiikuti oleh teks yang ingin Anda ganti dengan dan Escuntuk kembali ke mode normal.

(Anda menyebutkan bahwa kadang-kadang teks pengganti yang ingin Anda gunakan disimpan dalam "0register yank - perhatikan bahwa Anda dapat dengan cepat memasukkan ini tanpa harus mengetik ulang dengan menekan Ctrl+R0dalam mode sisipkan.)

Anda kemudian dapat melompat ke pertandingan berikutnya dan ulangi perubahan dengan satu .penekanan tombol!

Jika ada tempat di mana Anda tidak ingin melakukan penggantian, cukup tekan ununtuk membatalkan perubahan dan melompat ke pertandingan berikutnya.

1: cepat, dengan menggunakan saran lain pada halaman ini seperti *, Ctrl+RCtrl+W, dll Lihat juga komentar Peter Rincker ini selama lebih saran tentang bagaimana awalnya mengisi pencarian Anda.

Menggunakan Select Mode

(Saya belajar ini dari romainl 's posting di subreddit vim . Saya tidak tahu apakah dia diciptakan sendiri atau hanya lewat di.)

Mode pilih sedikit mirip dengan mode visual, kecuali jika Anda mulai mengetik teks yang dipilih segera diganti dengan apa yang Anda ketik (seperti cara kerja seleksi di sebagian besar editor lain).

Dengan demikian Anda dapat menggunakan trio pemetaan ini untuk melakukan pencarian / penggantian yang sangat cepat, yang dapat Anda ubah di pertengahan file, jika perlu:

nnoremap § *``gn<C-g>
inoremap § <C-o>gn<C-g>
snoremap <expr> . @.

Pemetaan mode normal : Memasuki mode pilih dengan kata terdekat dengan kursor yang dipilih.

Anda kemudian dapat mengetik pengganti untuk kata yang dipilih dan ( tanpa menekan Esc) gunakan:

Sisipkan pemetaan mode : Melompat ke pertandingan berikutnya dan memasuki mode pemilihan.

Anda kemudian dapat mengetik pengganti baru atau tekan .untuk menggunakan:

Pilih mode pemetaan : Masukkan kembali teks yang terakhir disisipkan - pada dasarnya, ulangi penyisipan terakhir.


Saya memang menyebutkan gnmetode di akhir jawaban saya vi.stackexchange.com/a/13696/488 kemarin untuk apa nilainya! Jawaban Anda memiliki format yang jauh lebih bagus.
TankorSmash

1
@TankorSmash Jadi Anda melakukannya! Perhatikan bagaimana saya melewatkannya. Perhatikan bahwa metode aktual yang saya gunakan berbeda dari Anda, meskipun (saya hanya memanggil gnsekali), dan itu metode khusus, (bukan hanya gnperintah) yang saya terkejut belum disebutkan.
Rich

Saya akan merekomendasikan memiliki beberapa jenis dari "bintang visual" plugin untuk digunakan dengan gn. Memberi Anda lebih banyak opsi pencarian. Orang miskin adalah pemetaan bintang visual yang: xnoremap * :<c-u>let @/=@"<cr>gvy:let [@/,@"]=[@",@/]<cr>/\V<c-r>=substitute(escape(@/,'/\'),'\n','\\n','g')<cr><cr>. Episode Vimcasts Terkait: Beroperasi pada pertandingan pencarian menggunakan gn
Peter Rincker

1
Saya telah membuat plugin sad.vim yang membantu aliran seperti itu.
Hauleth

7

Plugin https://github.com/terryma/vim-multiple-cursors menangani sebagian besar masalah ini.

Alur kerja saya biasanya sebagai berikut:

  1. Pindahkan kursor ke kata yang akan diganti.
  2. Tahan ctrl-nsampai semuanya dipilih.
  3. Tekan cdan mulai mengetik pengganti.

Hal yang nyaman di sini adalah Anda juga dapat melakukan operasi yang lebih rumit dari sekadar mencari-ganti, meskipun saya menemukan bahwa jika Anda mengambilnya terlalu jauh, plugin mulai menampilkan beberapa gangguan.


4

Cara lain untuk melakukan hal-hal yang belum disebutkan: Anda dapat menggunakan jendela baris perintah (dibuka dengan q:dalam mode normal - lihat :help q:untuk informasi lebih lanjut), di mana Anda memiliki akses penuh ke fitur pelengkapan otomatis Vim ( i_CTRL-N/ i_CTRL-Pdan berbagai i_CTRL-Xurutan berada di antara mereka).

Di jendela baris perintah Anda juga dapat menggunakan perintah mode normal untuk mengedit baris perintah, yang, misalnya, berarti Anda dapat menarik dan menempel bagian dari perintah sebelumnya dalam riwayat baris perintah Anda.

Perhatikan bahwa kursor Anda akan dipindahkan ke jendela baris perintah saat menggunakannya, artinya CTRL-R CTRL-Wdan metode serupa yang melibatkan memasukkan teks di bawah kursor tidak akan berfungsi di sana, tidak seperti di baris perintah biasa.


1
Anda juga dapat membuka jendela baris perintah saat Anda sudah setengah jalan memasukkan :substituteperintah dengan menekan<ctrl-f>
Rich

2

Solusi untuk ini agak di antara jawaban lain untuk saya:

Katakanlah Anda memiliki 6 garis yang identik, dan Anda ingin mengganti 'apel' di tengah dua:

I have apples for days
I have apples for days
I have apples for days
I have apples for days
I have apples for days
I have apples for days

Apa yang saya lakukan adalah:

  1. Saya memulai teks yang ingin saya ganti, 'apel'
  2. Tekan vuntuk masuk ke mode visual
  3. Turun ke kata terakhir yang ingin saya ganti, dalam hal ini beberapa baris jadi 2j
  4. :s/<C-R><C-W>/yang menggunakan pemilihan visual sebagai rentang untuk :s, dan kemudian menyisipkan kata di bawah kursor
  5. Saya menekan <C-F>yang menempatkan Anda ke mode di mana Anda dapat mengedit perintah Anda seolah-olah itu adalah buffer. Jadi Anda bisa menggunakan pelengkap atau plugin apa pun yang ingin Anda pilih kata penggantinya, dan Anda selesai.

Semua dalam satu baris, aliran untuk ini akan /apples<CR>2nv/apples<CR>nn:s/<C-R><C-W/oranges<CR>tetapi itu terlihat lebih buruk daripada itu.

Dalam kasus Anda, Anda dapat menambahkan /cke :sperintah untuk melewatkan yang tidak Anda inginkan, jika kisaran Anda berisi beberapa Anda ingin melewatkan: :s/<C-R><C-W/orange/c.

Atau (dan mungkin lebih sederhana), Anda bisa mencari seluruh kata yang ingin mengganti, change itu, kemudian gndan .mengulangi pencarian dan menerapkan perubahan yang sama lagi. Tampaknya akan /\<apple\><CR>viwcorange<ESC>gn.gn.gn..ngn.mengulanginya pada tiga, lalu lewati sebuah instance, lalu ulangi untuk yang terakhir kalinya.


Metode yang Anda jelaskan pada akhirnya tidak bekerja untuk saya (dalam Vim 7.4, dipanggil dengan vim -Nu NONE). Hanya berbunyi bip saat saya menekan yang pertama .. Adakah yang tahu mengapa itu terjadi? Bagaimanapun, itu akan lebih mudah untuk digunakan ciwdaripada viwdan nbukannya gnuntuk membuat perubahan dengan cara ini.
Kaya

2

Ini tidak sepenuhnya terkait dengan pertanyaan, tetapi masih harus membantu memilih kata yang akan diganti.

Pencarian tambahan ( set incsearch) memungkinkan Anda mengetikkan awalan kata yang perlu Anda temukan, dan vim akan secara otomatis beralih ke kemunculan awalan pertama saat Anda mengetik lebih banyak dan lebih banyak lagi. Pencarian akan dikonfirmasi jika Anda menekan Enter dan dibuang di Esc (dalam kasus terakhir kursor akan melompat kembali ke tempat itu sebelum pencarian dimulai).

Namun, pencarian tambahan menyediakan satu fitur lagi yang bermanfaat. Saat Anda sudah mengetik awalan kata dan kursor berada di posisi yang benar, tekan <C-L>untuk menambahkan karakter dari kata di bawah kursor ke string pencarian. Ini memungkinkan Anda untuk memasukkan string yang diganti dengan hampir tanpa penekanan tombol.

Jadi, jika saya ingin mengganti someOddVariableNamedengan evenOdderVariableName, saya

  1. ketik /someOddVdan sampai pada saat terjadinya someOddVariableName;
  2. tekan dan tahan <C-L>hingga someOddVariableNamemuncul di baris pencarian sepenuhnya;
  3. tekan Enter untuk mengonfirmasi pencarian;
  4. :%s//evenOdderVariableName/gatau yang mana pun menggantikan perintah yang Anda butuhkan; Anda mungkin ingin mengikuti jawaban lain di sini.

2

Anda dapat menempatkan nama variabel di buffer terlebih dahulu ( ywuntuk menyalin kata), lalu salin-tempel :%sdengan menekan <C-r>".


2

Jika Anda ingin mengganti variabel di dalam blok yang baru (ditempel), saya punya dua saran:

Ganti otomatis

  • Pergi ke baris pertama dari blok baru, tekan ma. Ini menandai lokasi dan menamakannya a.

  • Pergi ke baris terakhir dari blok baru, tekan mb. Sekarang Anda memiliki dua lokasi bernama.

  • Sekarang ganti antara dua garis, seperti: :'a,'bs/oldVarName/newVarName/g.

  • Artinya, ruang lingkup penggantian berada di antara dua nilai Anda.

Cara manual

  • Pergi ke baris pertama dari blok baru.

  • Gunakan /oldVarNameuntuk menemukan contoh pertama oldVarName.

  • Ubah seperti ini:, cwnewVarName<Esc>yang akan mengubah kata newVarNamedan memukul pelarian.

  • Gunakan nuntuk pergi ke contoh berikutnya dari oldVarName.

  • Gunakan .untuk mengulangi perubahan terakhir (yaitu mengulanginya cw).


2

Banyak jawaban lain di sini sudah mencakup cara-cara yang dibangun untuk meningkatkan alur kerja temukan-dan-ganti tapi saya ingin menyebutkan abolish.vim , sebuah plugin oleh Tim Pope. Itu membuat penggantian di mana Anda ingin mencakup berbagai kasus, biasanya disebabkan oleh variasi dalam kasus atau karena Anda perlu berurusan dengan bentuk kata tunggal dan jamak.

:S/child{,ren}/adult{,s}/gdikonversi dengan benar childke adult, Childrenke Adultsdan CHILDke ADULT.

Jika Anda berurusan dengan kata-kata cased camel, Anda harus memasukkan huruf kapital di mana Anda membutuhkannya dalam kata-kata asli dan pengganti.

%:S/wordWrap/textBreak/gdengan benar menangani keduanya wordWrapdan wordwrap.


0

Seperti yang telah ditunjukkan oleh orang lain, jika kursor Anda berada di atas kata Anda, Anda dapat menggunakan Ctrl + r keluarga perintah, karena Ctrl + r Ctrl + w mungkin yang paling cocok untuk digunakan.

Metode itu, bagaimanapun, hanya berfungsi untuk memasukkan satu kata (yang tepat di bawah kursor), tetapi bagaimana jika ada beberapa bagian teks dalam buffer yang ingin kita gunakan? Karena Anda tidak dapat memindahkan kursor saat berada di baris perintah. Cara terbaik untuk melakukan ini adalah dengan menyalin bagian-bagian teks yang akan Anda perlukan ke register yang berbeda, yang dapat Anda lakukan dengan mengawali "{reg_letter} (kutipan dan surat dari register) ke operator penyalinan. Dengan cara ini dimungkinkan untuk masukkan berbagai kata di baris perintah nanti dengan Ctrl + r {reg_letter}. Ini sedikit canggung tapi berfungsi.

Tetapi kembali ke ide sebelumnya, alangkah baiknya jika kita akan memindahkan posisi kursor di atas buffer sambil menulis sebuah pola. Dengan begitu kita bisa "mengambil" teks dari posisi yang berbeda dengan Ctrl + r Ctrl + w, jadi saya membuat plugin yang melakukan hal itu: EXtend.vim Plugin ini juga memiliki banyak fitur lain untuk melakukan operasi substitusi.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.