- Tim yang membuat Atom kembali mengurai tujuan yang sama di Zed—editor yang ringan tetapi memiliki fitur setingkat IDE—dengan basis Rust, UI berakselerasi GPU, CRDT, dan Tree-sitter
- Keterbatasan Atom pada 2017 lebih banyak terlihat dari kurangnya kendali atas memori dan rendering di Electron dan JavaScript, bukan dari kemampuan tim, dan inilah yang mengarah pada kesimpulan “harus memulai ulang”
- Rust memungkinkan Zed menangani memori bersama dan multithreading dengan lebih aman, serta memungkinkan snapshot O(1) yang dibutuhkan pekerjaan latar belakang melalui B-tree copy-on-write dan struktur rope berbasis
Arc - Zed mendapatkan kendali yang lebih rinci dengan memiliki sendiri lapisan inti seperti GPUI, ekstensi Tree-sitter, crate
editor, multi-buffer, dan SumTree, tetapi sebagai gantinya menanggung biaya kecepatan pengembangan dan onboarding - Hasil terpenting bagi pengguna adalah editor yang cepat, sementara struktur berbasis Rust dan
cargomemudahkan kontributor open source mencoba build dan perubahan serta meningkatkan kepercayaan saat merge
Bagaimana visi Atom berlanjut ke Zed
- Tujuan Zed mendekati bentuk yang lebih matang dari visi yang dulu pertama kali dikejar Atom
- Alat yang ringan, minimal, dan terasa seperti editor teks
- Alat yang menyediakan fitur setingkat IDE saat dibutuhkan, tetapi UI dan pengalaman pengguna tidak terasa lambat atau berat
- Editor yang dapat diperluas dan dapat di-scripting
- Ekstensibilitas Emacs memengaruhi visi awal, tetapi arahnya adalah mengakses representasi teks yang lebih kaya daripada sekadar memanipulasi per karakter
- Tree-sitter adalah fondasi yang memungkinkan teks diperlakukan secara lebih struktural daripada sebagai karakter, dan Zed belum dapat di-scripting, tetapi menargetkan arah tersebut
- Atom dimulai berbasis teknologi web; saat itu Rust belum ada, dan membuat editor native dengan C atau C++ juga dinilai sulit
Alasan memutuskan “memulai ulang” pada 2017
- Setelah Atom merilis Teletype pada 2017, batasan platform mulai terasa sebagai bottleneck yang lebih besar daripada kurang matangnya tim
- Array JavaScript berperilaku seperti array pointer objek sehingga ada biaya pelacakan pointer saat iterasi, dan sulit mengendalikan langsung tata letak memori serta jeda garbage collector
- Bahkan dalam upaya membuat layout baris lebih cepat, mereka harus menggabungkan iframe, Canvas, dan API pengukuran teks secara tidak langsung, sehingga pekerjaan yang tampak sederhana seperti posisi kursor atau penataan baris menjadi rumit
- Electron lahir untuk membuat Atom, tetapi sulit menyediakan tingkat kontrol yang dibutuhkan editor kode
- Dapat digunakan untuk aplikasi yang lebih sederhana, tetapi memiliki kekurangan berupa jejak memori yang besar
- Dalam editor kode, diperlukan kendali yang lebih langsung atas rendering, input, dan pemrosesan teks
- Pada suatu titik pada 2017, mereka menilai Atom tidak bisa mencapai tingkat yang diinginkan, lalu berangkat dari gagasan menulis inti dengan Rust sambil mempertahankan Electron sebagai lapisan presentasi
Proses berpindah ke Rust dan akselerasi GPU
- Pilihan teknologi Zed bukan cetak biru yang sudah tetap sejak awal, melainkan ditentukan bertahap sambil menghapus batasan satu per satu
- Pertama, mereka meninjau arah menulis inti dengan Rust
- Setelah itu, mereka meninggalkan Electron dan membuat framework UI sendiri
- Mereka menggunakan Pathfinder, tetapi karena terlalu lambat, mereka mempelajari dan menerapkan shader sendiri serta signed distance field
- Akselerasi GPU dipilih bukan berangkat dari slogan “editor berakselerasi GPU”, melainkan dari penilaian bahwa menggunakan langsung hardware yang dapat menghitung warna tiap piksel layar secara paralel bisa lebih cepat
- Alih-alih menyesuaikan node DOM, Zed memilih arah untuk mengendalikan rendering pada tingkat yang lebih dekat dengan cara menggambar piksel di layar
- Sebagai contoh peningkatan performa,
find-all-matchessebelumnya memakan sekitar 1 detik dan Sublime Text mendekati sekitar 200 ms, tetapi dengan hanya kode tingkat tinggi yang memanggil API internal, turun menjadi 4 ms pada release build - Waktu kompilasi Rust tetap menjadi keluhan, tetapi fakta bahwa performa dapat diharapkan bahkan di atas abstraksi tingkat tinggi bekerja secara berguna dalam pengembangan Zed
Batas JavaScript/C++ dan multithreading Rust
- Di Atom pun C++ banyak digunakan, tetapi batas antara kode aplikasi JavaScript dan kode library C++ menjadi biaya besar
- Untuk memindahkan pekerjaan ke thread latar belakang, subsistem terkait harus diturunkan ke C++
- Untuk memakai memori bersama, mereka harus membuat lapisan C++ lalu merancang lagi API JavaScript
- Mereka juga perlu membuatnya tampak seperti JavaScript sekaligus mempertahankan properti yang sudah ada
- Rust memiliki desain yang ramah multithreading sehingga lebih sesuai dengan cara yang diinginkan Zed
- Pada awalnya, mereka mencoba mengimplementasikan splay tree yang dapat diubah dan memiliki pointer induk di Rust, tetapi berbenturan dengan borrow checker hingga sempat meragukan apakah sistem nyata bisa dibuat
- Setelah itu, mereka membuat B-tree copy-on-write dengan menggunakan
Arc, dan struktur ini secara alami menjadi bentuk yang sesuai untuk multithreading - Rope, struktur penyimpanan teks dasar Zed, dapat ditangani dengan sekadar menaikkan reference count
Arcsaat meneruskan snapshot ke thread latar belakang
Pilihan untuk memiliki seluruh stack sendiri
- Zed memilih arah memiliki sendiri blok-blok besar, mulai dari Tree-sitter yang menangani parsing hingga GPUI, framework UI berakselerasi GPU
- Struktur kepemilikan langsung memungkinkan mereka menentukan dan mengimplementasikan sendiri perilaku yang dibutuhkan
- Saat ingin memakai WASM dalam ekstensi bahasa, mereka dapat menambahkan fitur tersebut ke Tree-sitter
- Mereka tidak perlu menyerahkan cara rendering teks yang penting bagi editor teks kepada framework UI eksternal
- GPUI dimulai pada 2019, dan framework UI yang ada saat itu tidak memenuhi perilaku yang dibutuhkan Zed atau belum cukup dipahami oleh tim
- Cara memahami primitif level rendah secara langsung dan membangun sistem adalah sesuatu yang mendekati strategi bertahan hidup di GPUI
- Biayanya juga jelas
- Membuat sendiri membutuhkan waktu lama
- Kecepatan pengembangan menjadi lebih lambat
- Karena tidak memakai framework yang sudah banyak dikenal, orang baru harus mempelajari codebase sekitar 300 ribu baris dari awal
- Pada saat yang sama, orang yang menulis kode tersebut ada di internal sehingga dapat menjelaskannya kepada anggota baru, dan mereka menilai seiring waktu biaya kepemilikan langsung dapat berkurang sementara manfaatnya terakumulasi
- Muncul juga contoh aplikasi lain yang dibuat di atas GPUI, seperti loungy
Bagian yang perlu dipoles dan bagian yang bisa dilewati cepat
- Standar tim Zed adalah membuat hanya yang dibutuhkan, lalu membuatnya sebaik mungkin dalam cakupan tersebut
- Alih-alih menghabiskan waktu menebak fitur yang mungkin dibutuhkan di masa depan, mereka mengimplementasikan hal yang benar-benar sudah dibutuhkan dengan niat dan perhatian
- Standar kelengkapan bergantung pada lapisan tempat kode berada
- Lapisan yang menjadi dependensi seluruh aplikasi seperti GPUI membutuhkan tingkat kelengkapan yang tinggi
- Struktur data yang digunakan di seluruh codebase dan penting bagi performa seperti SumTree juga ditangani dengan hati-hati
- Peningkatan performa tertentu di area tepi ditangani sampai memenuhi tujuan, bukan dipoles berlebihan
- SumTree menggunakan pengujian acak untuk memeriksa edge case
- Perfeksionisme tidak boleh menghambat pembelajaran, dan ketika kode buatan sendiri sudah dioperasikan lama, mengalami kompromi, lalu ditulis ulang, muncul dasar untuk penulisan ulang yang mencerminkan pembelajaran
Pelajaran dari CRDT dan struktur buffer
- Buffer awal Atom adalah array string JavaScript, yaitu array baris
- Buffer Zed adalah B-tree copy-on-write yang ramah multithread dan dapat di-snapshot, serta mengindeks berbagai item yang dibutuhkan
- CRDT bukan pilihan yang sudah jelas sejak awal; pendekatan saat ini dirumuskan setelah periode riset membaca berbagai makalah
- Implementasi CRDT ditulis ulang dua atau tiga kali, tetapi pendekatannya sendiri secara umum dipertahankan
- Pada Atom, editor kode pertama mereka, digunakan pendekatan “worse is better” yang lebih cepat dan kasar, dan dari pengalaman itu mereka memahami di mana titik sakit yang nyata
- Jika memulai ulang, mereka tidak akan membuat buffer sebagai array baris sederhana, karena contoh lambat dan edge case dari masa lalu menuntut desain yang lebih banyak pertimbangan
Lapisan yang sangat dipoles di Zed
- GPUI adalah area yang mengejar kelengkapan tinggi karena seluruhnya ditulis ulang
- Crate
editormencakup beberapa lapisan yang mengubah teks buffer mentah menjadi baris di layar- Ekspansi tab
- Soft wrapping
- Penyisipan dekorasi blok
- Penanganan fold
- Lapisan transformasi ini memiliki strategi pengujian yang konsisten menggunakan pengujian acak berbasis properti
- Multi-buffer adalah struktur yang menyatukan bagian dari buffer yang berbeda, dan juga diperlakukan sebagai inti
- Pada 2021, mereka pernah menghabiskan beberapa hari penuh untuk memperkecil dan men-debug edge case yang ditemukan pengujian acak
- Jika lapisan yang ditulis dengan Rust ini salah, bukan sekadar stack trace muncul di sudut editor, melainkan program bisa berhenti karena panic, sehingga akurasi penting
- Untuk mengurangi kondisi ketika pengguna membuka file besar tanpa menerima umpan balik apa pun, input yang lebih ramah streaming dan peningkatan loading juga dibahas, dan optimasi terkait dijadwalkan masuk ke preview
Perbedaan yang tersisa bagi pengguna dan kontributor
- Pengguna akhir pada akhirnya kemungkinan paling mementingkan apakah editornya cepat
- Pada alat developer dan editor, pengguna berpeluang besar ikut berkontribusi langsung ke codebase, sehingga bahasa implementasi dan cara build memengaruhi kemungkinan kontribusi
- Jika Zed ditulis dengan C++, jumlah pengguna yang ingin mengubahnya sendiri mungkin lebih sedikit
- Rust dan
cargomemudahkan orang membangun proyek dan mencoba perubahan, serta mengurangi kebutuhan mempelajari CMake atau Gyp - Ketegasan compiler Rust membantu meningkatkan kepercayaan saat merge dari sudut pandang penerima kontribusi eksternal
- Zed ingin menjaga frame tetap di bawah 3 ms, dan karena tuntutan performa ini mereka memilih framework UI berakselerasi GPU alih-alih rasterisasi CPU
- Mereka juga tertarik pada Zig, tetapi struktur satu bahasa dengan server dan frontend sama-sama memakai Rust memiliki keunggulan
1 komentar
Opini Hacker News
Framework UI kustom Zed mungkin terlihat menarik saat ini, tetapi situasinya akan berubah begitu mereka menyadari bahwa aksesibilitas harus diimplementasikan
Untuk mengimplementasikan aksesibilitas dalam framework kustom tanpa mengorbankan performa, dibutuhkan banyak pekerjaan rumit yang spesifik per platform. Zed memosisikan diri bukan sekadar sebagai editor yang bisa diabaikan, melainkan sebagai alat kolaborasi, jadi penting agar semua developer dalam tim bisa menggunakannya
Sebagai pengguna screen reader, saya sudah lelah dengan tool “modern” berbasis Rust yang hanya terlihat sebagai jendela kosong bagi VoiceOver. Dibandingkan aplikasi web yang cukup diberi beberapa label aria pada tombol dan dirapikan fokusnya, UI kustom yang harus mengekspos semua kontrol ke semua OS jauh lebih sulit
Untungnya, adanya AccessKit seperti https://accesskit.dev/ mungkin bisa sedikit mempermudah pekerjaan, tetapi saya tidak tahu seberapa cocok itu untuk aplikasi besar seperti editor
Karena GPUI dibuat dari awal, mereka tidak bisa begitu saja memakai fitur aksesibilitas yang dimiliki aplikasi berbasis Swift atau web, dan disebutkan bahwa pekerjaan di sisi Zed serta perluasan fitur GPUI harus berjalan bersama
Namun tautan diskusi aksesibilitas yang dipasang, https://github.com/zed-industries/zed/pull/1297, adalah isu GitHub terkait tombol mundur/maju, jadi tidak berguna. Sepertinya yang ingin mereka tautkan adalah https://github.com/zed-industries/zed/discussions/6576
Dokumen terkait: https://zed.dev/docs/themes
Mereka memang sudah memikirkan aksesibilitas, tetapi belum sampai tahap implementasi nyata
Hingga belum lama ini, yang ada hanya binding ke framework C yang sudah ada atau library GUI pada tahap proof of concept. Ke depannya mungkin akan membaik, tetapi saya juga memahami frustrasi pihak yang bergantung pada fitur aksesibilitas
Namun banyak proyek kemungkinan besar akan mencoba membuat library GUI yang solid terlebih dahulu, baru kemudian menambahkan fitur aksesibilitas
Banyak startup gagal karena menghabiskan sumber daya pada fitur mengilap yang bahkan bukan faktor pembeda
Produk yang berhasil dengan UI non-native umumnya memakai teknologi web atau framework matang seperti Qt, atau merupakan pengecualian seperti Blender yang sudah berusia 30 tahun. Apple juga melakukan hal serupa dengan iTunes, tetapi iTunes untuk Windows terasa menjengkelkan, dan orang-orang tetap memakai iTunes meski begitu
Saya memahami daya tarik untuk membuat framework seperti GPUI, tetapi tulisan itu tidak menjelaskan apa hubungannya dengan masalah yang ingin diselesaikan Zed
Maksudnya alat yang hanya melihat piksel lalu memahaminya seperti manusia, dan mem-parse teks dengan OCR
Saya memahami bahwa teknologi seperti VoiceOver mengetahui dan memanfaatkan definisi jendela serta elemen sebenarnya pada level pemrograman
Untuk proyek yang ingin mengejar kecepatan rendering GPU sehingga terlihat seperti “jendela kosong” bagi VoiceOver, cara seperti ini mungkin bisa menjadi alternatif minimal
Kalau begitu, saya juga penasaran apakah itu berarti semua konten yang dirender dengan GPU seperti game memang tidak dapat diakses
Di iPhone, saya membuat Apple Shortcut bernama “GPT Explains”; dengan mengetuk dua kali bagian belakang ponsel, shortcut itu mengambil screenshot, mengirimkannya ke OpenAI, lalu mengembalikan penjelasan tentang apa yang terlihat, terjemahan bahasa Inggris untuk teks non-Inggris, bantahan terhadap klaim meme, dan semacamnya
Salinan tanpa API key ada di sini: https://www.icloud.com/shortcuts/0d063c6810d74a35a017e5a5f69...
Sebelum ikut tren editor teks baru, saya tinggalkan ini sebagai ajakan untuk sekali melihat lisensi yang harus disetujui pengguna
“Customer Data yang terdiri dari konten pengguna yang dibuat selama penggunaan Solution diklasifikasikan sebagai User Content. User Content hanya dikirim dari lingkungan pengguna jika pengguna memilih berbagi proyek di Editor untuk berkolaborasi dengan pengguna Zed lain.”
“[...] akses Zed terhadap User Content tersebut dibatasi untuk debugging dan peningkatan Solution.”
Saya tidak akan memberi penjelasan terpisah, jadi silakan masing-masing menarik kesimpulan sendiri
Jika Anda memilih berbagi proyek dengan orang lain untuk berkolaborasi, tentu saja isi proyek itu akan dikirim keluar dari mesin Anda. Kalau tidak begitu, bagaimana bisa berfungsi?
Karena tulisan ini, saya mencoba Zed, dan terlihat cukup menjanjikan. Namun, karena tidak mendukung remote host/devcontainer, saya tidak bisa memakainya
Fitur VSCode ini adalah inti alur kerja saya. Saya sebenarnya tidak ingin mengembangkan di Mac; saya ingin memakai Mac seperti portal untuk masuk ke VM dan container tempat saya coding
Ini sangat membantu memisahkan proyek, dan dari sisi keamanan juga lebih baik karena tidak menaruh lingkungan pengembangan atau dependensi di mesin host sebenarnya
Saya penasaran apa keunggulan remote host/devcontainer VSCode dibanding sesi remote biasa
Sangat direkomendasikan; ini wawancara yang sangat bagus untuk melihat cara berpikir developer dalam memandang pengembangan dari berbagai sudut
Namun, ada satu hal yang kurang saya setujui
Bukan “nama yang pas untuk editor teks yang dibuat dengan Zig sudah diambil oleh Zed”, nama itu adalah “Zag” ;)
zedadaed.edadalah pendahuluex,vi,edlin, dan merupakan line editor keluarga Unix yang masih ada hingga kinihttps://en.wikipedia.org/wiki/Ed_(text_editor)
Sementara
ag, alias the silver searcher, juga luar biasa, tetapi menurut saya Zed lebih dekat ke pengeditan kode daripada pencarian kodehttps://geoff.greer.fm/ag/
Saya tidak memakai Zed, tetapi pernah melihat José Valim memakainya saat live coding. Saya terutama memakai VSCode, dan satu fitur yang saya lihat di Zed cukup menarik
Saat melakukan “Find All”, seperti di VSCode, potongan dari semua file yang cocok muncul di panel hasil, tetapi di sana ia bisa mengedit potongan hasil pencarian secara langsung, dan fitur pengeditan umum seperti multi-cursor juga tetap bisa dipakai
Di VSCode, kita harus mengeklik hasil pencarian untuk membuka file lalu mengubahnya di sana, jadi ini terasa cukup keren dan mengesankan. Belum sampai membuat saya beralih, tetapi kadang teringat setiap kali VSCode membuat kesal
occurdanmulti-occursejak tahun 80-an, dan pekerjaan seperti ini bisa dilakukan. Benar-benar luar biasaBelakangan ini, antarmuka untuk alat seperti ripgrep juga menyediakan mode yang bisa diedit, sehingga sangat praktis untuk refactoring. Tentu saja nama file juga bisa diedit massal
https://www.masteringemacs.org/article/searching-buffers-occ...
https://rgel.readthedocs.io/en/latest/
https://www.gnu.org/software/emacs/manual/html_node/emacs/Wd...
Ini mungkin terdengar konyol, tetapi salah satu alasan utama saya memakai JetBrains alih-alih VSCode adalah karena saya bisa mencari direktori dan membukanya di panel navigasi
Baru setelah melihat komentar ini saya teringat bahwa saya sempat melupakannya, jadi saya harus mencobanya lagi
https://marketplace.visualstudio.com/items?itemName=jakearl....
Salah satu trik favorit saya adalah mengedit dengan multi-cursor lalu memakai pintasan pindah ke akhir baris atau kata berikutnya untuk melakukan perubahan massal
Akan bagus kalau itu bisa dilakukan di banyak file
Tidak berjalan di Windows atau Linux. Kalau sudah didukung, saya harap diberi tahu lagi
Wawancara yang luar biasa
Saya suka bagaimana mereka berpikir mendalam tentang apa yang perlu dipoles secara berlebihan. Rasanya karya terbaik saya juga biasanya muncul di putaran kedua, ketiga, atau keempat
Saya penasaran apa rencana untuk kemampuan menangani konfigurasi lewat skrip. Saya belum banyak memakai Zed; apakah itu sudah bisa dilakukan sekarang? Apakah sesuatu seperti Neon akan membantu menjembatani kesenjangan antara pengguna VSCode dan mantan pengguna Atom?
https://github.com/neon-bindings/neon
— Brooks, Mythical Man-Month
Melihat v2 selalu menarik. Saya pernah melihatnya menjadi bencana karena kelebihan fitur, dan juga melihatnya menjadi hebat karena lebih ringkas dan lincah
Di bidang aplikasi web saat ini, alatnya begitu banyak sehingga saya penasaran apakah risiko ini berlaku sama pada v1, bukan hanya v2. Saya sering melihat v1 belakangan ini juga mengejutkan bengkaknya, dan sering kali harus sengaja mencari alat yang melakukan lebih sedikit hal
Saya sudah mencoba Zed dan rasanya mirip dengan VSCode. Saya tahu ada fitur multiplayer yang lebih baik daripada Live Share, tetapi dari tampilan luarnya, saya masih perlu alasan yang lebih meyakinkan untuk beralih
Kalau Zed bisa menggantikan Xcode, rasanya saya ingin mencobanya lebih jauh. Dari menghapus derived data atau membersihkan build folder sampai crash acak, memakai Xcode itu menyakitkan
Dibandingkan dengan pengalaman developer di Android Studio, rasanya benar-benar berbeda. Dalam pengembangan iOS, saya selalu menginginkan pengalaman seperti Android Studio
Saya sangat menyukai aplikasi native, tetapi saat ini terikat pada VS Code. Melihat kedipan kursor saja di VS Code memakai daya cukup besar membuat saya miris
Saya sempat mencoba Zed, tetapi belum bisa menyesuaikannya dengan alur kerja saya. Saya suka karena ringan dan cepat. Proses-proses VS Code sekitar 3GB, sedangkan Zed 300MB, jadi sepersepuluh memori adalah perbedaan yang berarti
Namun saya benar-benar membutuhkan dukungan Jupyter Notebook yang disediakan VS Code, dan sudah terlalu terbiasa dengan cara remote development dari Mac ke mesin Ubuntu. VS Code melakukan ini dengan sangat baik
Saya berharap Zed bertahan cukup lama sampai mendukung alur kerja saya
Mungkin semua orang mengaktifkan lebih banyak extension
Menurut efek Lindy https://en.wikipedia.org/wiki/Lindy_effect, sepertinya masih butuh satu tahun lagi sampai kita melihat sesuatu
Saya melihat halaman About, dan fitur live coding terlihat berguna. Para developernya juga tampaknya antusias. Ini proyek yang menyenangkan karena bisa menulis algoritme, mengoptimalkan performa, dan melakukan pemrograman GPU
Namun saya bertanya-tanya siapa yang membutuhkan satu lagi editor teks yang mungkin selamanya tidak akan mencapai kesetaraan fitur dengan Vim dan terminal multiplexer
VS Code muncul tiba-tiba relatif baru-baru ini dan digunakan banyak orang, jadi itu menunjukkan bahwa masih ada peluang bagi editor baru setelah Vim
Apakah Zed akan mendapat momentum yang cukup untuk memenuhi kebutuhan long tail developer lain masih harus dilihat, tetapi cukup menarik melihat lebih banyak produk bersaing untuk mendapatkan pengguna
Tanpa perlu meniru Vim, editor bisa langsung memanfaatkan Neovim dan semua pluginnya apa adanya
Saya masih menyayangkan JetBrains terus mempertahankan plugin peniru Vim yang disebut buruk oleh pengguna Vim. Jika mereka mengimplementasikan frontend Neovim secara native di IDE, itu akan menjadi keunggulan yang jauh lebih kuat: “mendukung Neovim dan ekosistemnya sepenuhnya”, bukan sekadar “ada plugin mirip Vim” seperti sekarang
Pakailah alat yang Anda suka dan yang membantu menyelesaikan pekerjaan. Itu termasuk Vim, tetapi saya lelah melihat sikap seolah-olah memakai Vim adalah berkah yang tak tergantikan
Menjadi pemikir yang lebih baik meningkatkan produktivitas sebagai programmer secara eksponensial, lebih dari alat apa pun
Sudah ada editor yang cukup kaya fitur dan membuat orang puas, atau setidaknya sudah terbiasa. Editor baru bisa mengambil posisi di mana?
“Multiplayer” memang keren, tetapi lebih dekat ke edge case
Model bisnisnya juga belum meyakinkan. Apakah orang benar-benar ingin channel, panggilan, dan chat terintegrasi ke editor kode? Secara pribadi saya hampir secara naluriah merasa menolaknya, meski mungkin hanya saya