Raw string """...""" memecahkan masalah penulisan teks multi-baris, tetapi membawa masalah baru: indentasi dari kode sumber ikut tersimpan dalam string. Tanpa perawatan khusus, blok JSON atau SQL yang ditulis menjorok di dalam function akan berisi whitespace yang tidak diinginkan pada hasil cetak. Kotlin menyediakan dua method untuk merapikan situasi ini: trimIndent() yang menghapus indentasi umum secara otomatis, dan trimMargin(prefix) yang menggunakan penanda eksplisit. Pada chapter ini kita akan membedah keduanya beserta pola penggunaan yang umum di proyek nyata.
Masalah: Indentasi Ikut Tersimpan #
Saat kita menulis raw string di dalam function, kode sumber biasanya menjorok beberapa level. Indentasi tersebut ikut tersimpan dalam string:
fun cetak() {
val teks = """
Baris pertama
Baris kedua
"""
println(teks)
}Output di atas akan berisi baris kosong pertama, lalu delapan spasi sebelum Baris pertama, dan empat spasi sebelum """ penutup. Untuk mendapatkan output yang rapi, kita perlu membersihkan indentasi.
trimIndent — Hapus Indentasi Umum #
Method trimIndent() melakukan tiga langkah: (1) membuang baris kosong di awal dan akhir, (2) mendeteksi indentasi minimum di seluruh baris non-kosong, (3) memotong indentasi sebesar itu dari setiap baris. Hasilnya adalah string yang setiap barisnya dimulai dari kolom 0 relatif terhadap indentasi paling sedikit di sumber.
val teks = """
Baris pertama
Baris kedua
Baris ketiga
""".trimIndent()
println(teks)Output:
Baris pertama
Baris kedua
Baris ketigaAturan indentasi minimum penting ketika beberapa baris memiliki indentasi yang berbeda. Misalnya, jika satu baris menjorok empat spasi dan baris lain menjorok delapan spasi, trimIndent akan memotong empat spasi dari semua baris — sehingga baris yang menjorok delapan tetap memiliki empat spasi tambahan sebagai indentasi internal.
trimMargin — Penanda Eksplisit #
Method trimMargin() menghapus semua karakter whitespace sebelum tanda margin (default |) dan tanda margin itu sendiri, untuk setiap baris. Pendekatan ini memberi kontrol eksplisit: hanya karakter setelah | yang dipertahankan. Hal ini berguna ketika baris memiliki indentasi internal yang sengaja dibuat tidak rata.
val teks = """
|Baris pertama
|Baris kedua
|Baris ketiga
""".trimMargin()
println(teks)Karakter margin default adalah |, tetapi bisa diganti dengan parameter: trimMargin("#"), trimMargin(">"), dan seterusnya. Pemilihan karakter margin penting bila konten string mengandung | sebagai karakter data (misalnya pada SQL dengan operator ||).
Pola Umum: SQL dan Surat #
Dua pola yang paling sering ditemui adalah query SQL dan template surat. Untuk SQL, trimIndent sudah cukup karena tidak ada indentasi internal yang perlu dipertahankan:
val sql = """
SELECT id, nama
FROM pengguna
WHERE aktif = true
""".trimIndent()Untuk surat dengan indentasi paragraf, trimMargin lebih cocok karena kita bisa menjorokkan baris tertentu secara sengaja:
val surat = """
|Halo pelanggan,
|Terima kasih telah berlangganan.
| (catatan: mohon periksa email kedua)
|Salam hangat,
""".trimMargin()Baris (catatan...) memiliki dua spasi sebelum | yang akan dihapus, tetapi dua spasi setelah | tetap menjadi indentasi internal yang sengaja dibuat.
Contoh Lengkap dan Outputnya #
File trim.kt berikut membandingkan keempat pendekatan secara berurutan:
fun main() {
val tanpaTrim = """
Baris pertama
Baris kedua
Baris ketiga
"""
println("Tanpa trimIndent:")
println("[${tanpaTrim}]")
println("---")
val denganTrimIndent = """
Baris pertama
Baris kedua
Baris ketiga
""".trimIndent()
println("Dengan trimIndent:")
println("[${denganTrimIndent}]")
println("---")
val denganMargin = """
|Baris pertama
|Baris kedua
|Baris ketiga
""".trimMargin()
println("Dengan trimMargin (default |):")
println("[${denganMargin}]")
println("---")
val denganPrefixKhusus = """
#Baris pertama
#Baris kedua
#Baris ketiga
""".trimMargin("#")
println("Dengan trimMargin('#'):")
println("[${denganPrefixKhusus}]")
println("---")
val indentCampuran = """
|Pertama
| Kedua menjorok
|Ketiga
""".trimMargin()
println("Dengan indent internal:")
println("[${indentCampuran}]")
println("---")
val sql = """
|SELECT id, nama
|FROM pengguna
|WHERE aktif = true
""".trimMargin()
println("Query dengan trimMargin:")
println(sql)
println("---")
val template = """
|Halo ${'$'}{nama},
|Selamat datang di layanan kami.
""".trimMargin()
println("Template surat:")
println(template)
}Output yang Dihasilkan:
Tanpa trimIndent:
[
Baris pertama
Baris kedua
Baris ketiga
]
---
Dengan trimIndent:
[Baris pertama
Baris kedua
Baris ketiga]
---
Dengan trimMargin (default |):
[Baris pertama
Baris kedua
Baris ketiga]
---
Dengan trimMargin('#'):
[Baris pertama
Baris kedua
Baris ketiga]
---
Dengan indent internal:
[Pertama
Kedua menjorok
Ketiga]
---
Query dengan trimMargin:
SELECT id, nama
FROM pengguna
WHERE aktif = true
---
Template surat:
Halo ${nama},
Selamat datang di layanan kami.Mari kita telaah bagian penting dari kode di atas. Blok pertama tanpaTrim membungkus string dalam tanda [...] agar terlihat baris kosong dan indentasi yang ikut tersimpan — perhatikan baris kosong pertama dan spasi sebelum Baris pertama. Blok denganTrimIndent menghapus baris kosong di awal/akhir serta indentasi minimum delapan spasi, menghasilkan tiga baris rapi tanpa spasi awal. Blok denganMargin memakai prefix | sebagai penanda; semua karakter sebelum | (termasuk spasi) dihapus. Blok denganPrefixKhusus menunjukkan parameter kustom # berguna ketika konten mengandung |. Blok indentCampuran memperlihatkan indentasi internal yang sengaja dibuat: Kedua menjorok tetap memiliki dua spasi setelah trimMargin. Terakhir, blok template menggunakan ${'$'}{nama} untuk menyisipkan teks literal ${nama} (bukan template) — sebuah trik untuk menulis template string yang akan diproses di tahap berikutnya.
Perbandingan trimIndent vs trimMargin #
| Aspek | trimIndent() | trimMargin(prefix) |
|---|---|---|
| Strategi | Indentasi minimum otomatis | Penanda eksplisit |
| Karakter penanda | Tidak ada | ` |
| Indentasi internal | Dipertahankan relatif terhadap minimum | Harus ditulis setelah penanda |
| Cocok untuk | Teks rapi satu level | Teks dengan indentasi beragam |
| Risiko | Salah bila ada baris tak sengaja menjorok | Lupa menulis ` |
Referensi Lanjutan #
- Strings
— bagian
trimIndent()dantrimMargin()pada panduan strings
Penutup #
Dengan trimIndent dan trimMargin, kita kini punya alat lengkap untuk menyusun teks multi-baris yang rapi secara visual di sumber sekaligus bersih di output. Selanjutnya, kita akan masuk ke topik pencocokan pola yang lebih kompleks: regular expression — fitur yang memungkinkan kita mencari, memvalidasi, dan mengganti teks berdasarkan pola, bukan literal.