Fish-shell: PATH/MANPATH/CDPATH dengan casing khusus aneh; kita membutuhkan solusi yang lebih umum seperti variabel zsh "terikat"

Dibuat pada 11 Des 2012  ·  52Komentar  ·  Sumber: fish-shell/fish-shell

Dalam expand.h :

/** Character for separating two array elements. We use 30, i.e. the ascii record separator since that seems logical. */
#define ARRAY_SEP 0x1e

/** String containing the character for separating two array elements */
#define ARRAY_SEP_STR L"\x1e"

Ini menghasilkan:

xiaq<strong i="10">@blackie</strong> ~> set a (printf 'a\x1eb')
xiaq<strong i="11">@blackie</strong> ~> count $a
2
xiaq<strong i="12">@blackie</strong> ~> set a (printf 'a\x1fb')
xiaq<strong i="13">@blackie</strong> ~> count $a
1

Jelas bahwa char \x1e diperlakukan secara khusus sebagai pembatas elemen.

enhancement

Semua 52 komentar

Apakah kekhawatiran bahwa tidak ada cara untuk mewakili \x1e? Atau apakah Anda berpikir tentang perbaikan arsitektur?

Saya pikir pemisah array terutama digunakan dalam array yang bertahan di tempat-tempat yang hanya mengambil string, seperti variabel universal atau variabel lingkungan.

12-12-12 2:09, notifikasi "ridiculousfish"@github.com写道

Apakah kekhawatiran bahwa tidak ada cara untuk mewakili \x1e? Atau apakah Anda berpikir?
tentang perbaikan arsitektur?

Saya akan mengatakan bahwa saya memiliki kedua masalah dalam pikiran. Untuk yang pertama, pikirkan saja
nama file dengan \x1e. POSIX mengatakan apa pun kecuali \0 diizinkan masuk
nama file, jadi itu sangat mungkin. Menggunakan \0 sebagai pembatas array mungkin
pilihan yang sedikit lebih baik, tetapi itu mengarah ke masalah kedua - itu
rapuh dan jelas salah.

Saya pikir pemisah array terutama digunakan dalam array yang bertahan di beberapa tempat
yang hanya mengambil string, seperti variabel universal atau variabel lingkungan.

Jika bertahan berarti "berseri", tidak. Array selalu disimpan di
\x1e-bentuk yang dibatasi. Array lingkungan yang diekspor digabungkan dengan ":". Mereka
digunakan dalam variabel universal - IMHO mana yang harus diterapkan
dengan melarikan diri yang tepat sebagai gantinya.


Balas email ini secara langsung atau lihat di GitHub.

Bagaimana dengan menggunakan karakter area penggunaan pribadi sebagai pemisah? Ikan sudah menggunakan beberapa dari mereka dalam beberapa kasus.

@JanKanis Itu tidak lebih baik; itu sangat mungkin dalam nama file (mengingat sistem file menggunakan non-utf8, penyandian asli) dan string lainnya.

Saya akan mengatakan bahwa antara lain, "\0" adalah _sedikit_ pilihan yang lebih baik di antara yang lain, karena itulah satu-satunya karakter yang dilarang UNIX dalam nama file, tetapi masih memiliki bau yang tidak enak bagi saya. Juga, kami sudah melakukan banyak pemisahan dan perakitan array, saya berharap menerapkan array yang benar untuk menghasilkan arsitektur yang lebih baik dan kode yang lebih sedikit.

Fish sudah menangani karakter penggunaan pribadi dan byte yang tidak valid saat mengkodekan string eksternal ke wchars. Nilai-nilai khusus ini dikodekan byte demi byte ke dalam kumpulan karakter penggunaan pribadi tertentu yang juga didekodekan oleh ikan pada output, jadi pada prinsipnya menggunakan karakter penggunaan pribadi lain dapat berfungsi. Namun saya setuju menggunakan array yang benar jauh lebih baik. Ada satu komplikasi dalam komunikasi antara ikan dan fishd terjadi melalui soket menggunakan string utf8, dan di sana ikan menggunakan (saya pikir) urutan pelarian "\x1e" (bukan 0x1e byte) untuk memisahkan item array. Tapi itu mungkin bisa diselesaikan dengan menggunakan misalnya urutan pelarian pribadi yang tidak digunakan.

Saya berbagi kekhawatiran xiaq, tetapi (untuk yang praktis) saya menemukan pemisahan implisit pada \n jauh lebih ofensif:

a<strong i="6">@raspeball</strong> ~> count (printf 'a\x1eb')
1
a<strong i="7">@raspeball</strong> ~> count (printf 'a\nb')
2

Interpretasi array (dibatasi baris baru) dari output subproses harus eksplisit & opsional!

Tapi itu mungkin tidak ada hubungannya dengan penyimpanan array yang mendasarinya…

@xiaq : Apa yang salah dengan menggunakan \0 ? xargs tampaknya menggunakannya sebagai opsi "dapat diandalkan".

Anda tidak dapat menggunakan \0 dalam variabel lingkungan, jadi akan sulit untuk mengekspor array ke shell anak.

Saya bermigrasi dari zsh tempat saya menggunakan urutan ini untuk mendefinisikan $LESS env var dengan cara yang waras dengan memanfaatkan fitur variabel "terikat":

typeset -xT LESS less ' '
less=(
    --HILITE-UNREAD
    --LONG-PROMPT
)

Saya telah menghilangkan daftar lengkap opsi untuk singkatnya. Dalam zsh yang menghasilkan $LESS env var menjadi daftar opsi yang dipisahkan spasi dalam array $less. Setara dalam ikan menghasilkan elemen yang dipisahkan oleh karakter pemisah rekaman (\x1e). Meskipun dokumentasi mengatakan bahwa elemen array akan dipisahkan oleh spasi (modulo array khusus seperti PATH). Saya harus secara eksplisit melakukan tugas yang menginterpolasi nilai menjadi satu string untuk mendapatkan hasil yang diharapkan:

set -x LESS --HILITE-UNREAD \
    --LONG-PROMPT
set LESS "$LESS"

Saat ini saya tidak terlalu peduli jika \x1e digunakan secara internal untuk membuat serialisasi array daripada \x00. Saya peduli bahwa array yang diekspor memiliki elemen yang dipisahkan oleh \x1e. Itu baru saja rusak, salah, fubar. Pilih kata sifat Anda. Ini juga tidak konsisten dengan solusi yang disebutkan di atas dan perilaku yang didokumentasikan. Masalah ini harus ditandai sebagai bug IMHO.

PS, Tidak ada tempat dalam dokumentasi yang menggunakan karakter pemisah rekaman (\x1e) yang disebutkan. Yang merupakan masalah lain.

@krader1961 Terima kasih telah berbagi ini. Tidak ada konvensi Unix standar untuk variabel lingkungan seperti daftar - beberapa dibatasi titik dua, yang lain dibatasi spasi. ikan menggunakan \x1e sehingga dapat membedakan arraynya sendiri.

Bisakah Anda mengarahkan kami ke dokumentasi yang salah?

Bagaimana menurut Anda array diekspor - titik dua, spasi, baris baru, sesuatu yang lain? Haruskah ikan memberi token pada variabel lingkungan pada karakter ini juga?

Sepertinya less mengharapkan argumen yang dibatasi ruang. Mungkin solusi paling sederhana adalah set -x LESS '--HILITE-UNREAD --LONG-PROMPT' , dll.

Tidak ada standar untuk daftar seperti variabel lingkungan karena menurut definisi mereka adalah urutan byte yang berubah-ubah yang terdiri dari kunci dan nilai yang dipisahkan oleh tanda sama dengan dan diakhiri oleh byte nol. Mereka bahkan tidak harus berupa karakter yang dapat dicetak. Satu-satunya konvensi yang diterima secara luas untuk tingkat abstraksi yang lebih tinggi adalah yang dibuat oleh fungsi execlp() untuk PATH env var.

Dokumentasinya salah sejauh tidak menyebutkan penggunaan karakter \x1E, \036, 30, atau "record separator" untuk memisahkan elemen array saat mengekspor var dengan lebih dari satu elemen. Dokumentasi memang menyatakan bahwa

..., and array variables will be concatenated using the space character.

Itu dari bagian "Ekspansi variabel" di http://fishshell.com/docs/current/index.html. Masuk akal untuk menyimpulkan bahwa pernyataan itu juga berlaku untuk var yang diekspor yang tidak berhuruf khusus seperti yang didokumentasikan di bagian "Array" dan "Variabel khusus" dari dokumen yang sama.

Perasaan saya bahwa ikan seharusnya tidak secara otomatis memasukkan env vars ke dalam daftar di luar vars kasus khusus yang dibatasi titik dua seperti PATH. Namun, harus ada sarana yang kuat di mana pengguna dapat menandai var ke dalam array pada karakter arbitrer.

Tidak adanya mekanisme untuk mengonfigurasi karakter yang akan digunakan pada basis var demi var (ala perintah zsh "typeset -T"), spasi harus digunakan saat menggabungkan elemen array (sekali lagi, tidak termasuk vars kasus khusus yang dipisahkan titik dua ). Jelas ini tidak berlaku untuk penyimpanan data pribadi seperti penyimpanan variabel universal.

Terakhir, saya tidak dapat menemukan kegunaan apa pun dalam fungsi ikan standar di mana env var digunakan untuk meneruskan array yang berisi lebih dari satu elemen ke fungsi atau skrip lain. Kasus penggunaan seperti itu mungkin ada tetapi skrip harus secara eksplisit bekerja sama dalam serialisasi/deserialisasi data daripada mengandalkan ikan untuk merekonstruksi array secara implisit dari vars yang stringnya berisi karakter pemisah rekaman.

Terima kasih atas tanggapan Anda yang bijaksana. Bagian yang Anda kutip tentang penggabungan menggunakan spasi khusus untuk string yang dikutip ganda. Kita harus menambahkan beberapa diskusi tentang apa yang terjadi dengan array yang diekspor.

Pengguna dapat menandai string dengan misalnya set SOMEPATH (string split : $SOMEPATH) .

Kelemahan dari variabel-variabel yang diekspor dengan penggabungan-ruang adalah variabel tersebut berubah ketika ikan dijalankan secara rekursif. Hari ini ini berfungsi:

> set -x list 1 2 3
> count $list
3
> fish -c 'count $list'
3

Tetapi jika kami mengekspor dengan spasi, ini akan menampilkan 1 untuk panggilan rekursif. Seperti yang Anda katakan, kami tidak bergantung pada ini, tetapi ini bagus dari sudut pandang konsistensi.

Terima kasih atas tanggapan Anda yang bijaksana.

Aku harus kedua itu! Selalu menyenangkan untuk memiliki perspektif baru tentang berbagai hal.

Bagi mereka yang baru dalam diskusi ini, saya pikir saya harus memasukkan beberapa hal yang berhubungan dengan ini.

Apa yang langsung terlintas dalam pikiran adalah daftar putih listify , yang muncul dalam masalah seperti #2090.

Ini berarti bahwa untuk $PATH, $CDPATH dan $MANPATH, mereka akan muncul sebagai daftar/array untuk memancing, tetapi ketika diekspor, akan digabungkan dengan ":" lagi. Kemudian ikan di dalam ikan akan membelahnya lagi. Ini beroperasi pada titik dua, bukan \x1e. Dari pemahaman saya tentang kode , tampaknya melakukannya pada setiap titik dua, tanpa peluang untuk melarikan diri, jadi itu mungkin merusak entri $PATH dengan titik dua di dalamnya - yang memungkinkan UNIX di dalam jalur file, meskipun tampaknya rusak untuk $PATH setidaknya . Skema ini juga digunakan untuk misalnya PYTHONPATH dan GOPATH.

Saya ingin memiliki sesuatu yang sedikit lebih eksplisit untuk memisahkan variabel lingkungan daripada selalu-split-on-\x1e-kecuali-untuk-ini-tiga-split-mereka-di-kolon implisit, karena ini sebenarnya adalah dua skema berbeda di satu dan mengekspor daftar saat ini akan selalu membingungkan segalanya kecuali ikan.

Solusi pilihan saya adalah fungsi seperti splitenv var1 var2 var3 :

function splitenv --no-scope-shadowing
    set -e IFS # string split doesn't have superpowers, so unset IFS lest we split on both : and \n
    for arg in $argv
        set -q $arg; and set $arg (string split ":" $$arg)
    end
end

(Jika string split memiliki kekuatan super , ini akan menjadi sedikit lebih sederhana)

Semua daftar kemudian akan digabungkan dengan titik dua saat diekspor, sehingga pengguna dapat secara eksplisit membatalkannya dengan splitenv (walaupun saya tidak mati-matian pada fungsi pembantu, saya yakin membuat ini sepele adalah baik sesuatu yang harus dikerjakan). Untuk kompatibilitas mundur, splitenv PATH CDPATH MANPATH akan dieksekusi saat startup. Jika pengguna ingin mengekspornya secara berbeda, string join tersedia.

Semua ini berarti bahwa kita tidak lagi membutuhkan \x1e, kita memiliki skema yang setidaknya memiliki kesempatan berjuang untuk dipahami oleh program lain, tetapi ikan-dalam-ikan (yang agak eksotis) sekarang menjadi fish -c 'splitenv list; count $list' .

Masalahnya tentu saja, seperti yang disebutkan, skema daftar yang dipisahkan titik dua yang biasa tidak memiliki cara untuk keluar dari titik dua, dan jika kita ingin menambahkannya, string split tidak memiliki "--unescaped" opsi untuk hanya membagi pada pemisah yang tidak lolos.

Apakah saya masuk akal?

@faho Saya pikir ide itu pantas. Bagian terburuk dari skema lama secara implisit membelah pada titik dua, yang akan menghancurkan variabel yang tidak boleh dipisah. Dalam ide Anda ini (hampir) selalu eksplisit jadi saya pikir ini cukup aman.

Mengenai melarikan diri, tidak melarikan diri dari titik dua di PATH disengaja per tautan yang Anda temukan. Saya ragu PYTHONPATH, CLASSPATH, dll. Lebih konsisten dalam hal ini. Karena Anda tidak dapat menggunakan titik dua di jalur ini, kami dapat memilih apakah kami akan menghindarinya atau tidak; tetapi jika kita lolos dari titik dua, kita perlu menghindari garis miring terbalik, dan saya yakin Anda dapat memiliki garis miring terbalik di PATH. Kami mungkin memerlukan daftar putih "jangan kabur" (ugh).

Atau kita tidak perlu khawatir tentang itu, dan biarkan titik dua apa pun bertindak sebagai pembatas. Saya pikir saya condong ke arah ini untuk kesederhanaan dan keakraban dengan cangkang lainnya.

Kami masih dihadapkan pada masalah bahwa beberapa variabel seperti daftar dibatasi oleh spasi, dan yang lainnya dibatasi oleh titik dua. Satu kemungkinan adalah splitenv menerima pembatas, mengingatnya, dan menggunakannya untuk membangun kembali nilai pada ekspor:

splitenv --on ' ' LESS
splitenv --on ':' PYTHONPATH

Panggilan ini sekarang memainkan peran ganda dalam mengimpor variabel yang ada, dan menandai bagaimana variabel tersebut diekspor. Bagaimana menurutmu?

Juga, apakah ada cara untuk melakukan ini tanpa mengedit config.fish? Mungkin sebagai bagian dari variabel universal?

Kami masih dihadapkan pada masalah bahwa beberapa variabel seperti daftar dibatasi oleh spasi, dan yang lainnya dibatasi oleh titik dua. Satu kemungkinan adalah bahwa splitenv menerima pembatas, mengingatnya, dan menggunakannya untuk membangun kembali nilai pada ekspor:

Kedengarannya bagus. Meskipun pada saat itu membuat skrip splitenv mungkin tidak akan membantu, karena kami tetap membutuhkan kerja sama dari sisi C++.

Panggilan ini sekarang memainkan peran ganda dalam mengimpor variabel yang ada, dan menandai bagaimana variabel tersebut diekspor.

Mungkin sekarang "splitenv" bukan nama yang sempurna lagi (itu ketika saya memikirkannya, tentu saja :laughing: ) - Saya juga mempertimbangkan "listify".

Meskipun itu mengganggu saya bahwa saya tidak dapat mengingat di mana kami memiliki diskusi terkait sebelumnya - saya pikir saya harus menjelajahi masalah lagi malam ini.

Pengguna dapat menandai string dengan misalnya set SOMEPATH (string split : $SOMEPATH) .

Perintah string tidak didokumentasikan di mana pun saya dapat menemukan. Juga, man string menampilkan halaman manual string(3) yang mendokumentasikan fungsi manipulasi string pada BSD (dan Mac OS X).

Tetapi jika kami mengekspor dengan spasi, ini akan menampilkan 1 untuk panggilan rekursif. Seperti yang Anda katakan, kami tidak bergantung pada ini, tetapi ini bagus dari sudut pandang konsistensi.

Perilaku itu, bagaimanapun, mengejutkan. Saya berani bertaruh bahwa jika Anda bertanya kepada 100 orang apa yang terjadi ketika var dengan lebih dari satu elemen diekspor, 90 dari mereka akan mengatakan nilainya digabungkan dengan spasi sebagai pemisah. Beberapa orang mungkin mengatakan koma atau karakter lainnya digunakan sebagai pemisah. Dan dua orang yang menjalankan env akan mengatakan nilainya digabungkan tanpa pemisah karena kecuali jika Anda memfilter output melalui sesuatu seperti cat -evt karakter pemisah rekaman tidak terlihat.

yang muncul dalam masalah seperti #2090

Maaf, tapi saya tidak melihat manfaat dari keluhan pengguna itu. Masalahnya sepele diselesaikan dengan secara eksplisit menguji apakah MANPATH sudah disetel. Yang, menurut saya, adalah sesuatu yang harus Anda lakukan dalam hal apa pun mengingat semantik memimpin versus mengikuti titik dua.

jadi itu mungkin merusak entri $PATH dengan titik dua di dalamnya

Setidaknya tiga puluh tahun sudah terlambat untuk memperbaikinya. Kita tidak boleh menerapkan pelolosan titik dua (dan dengan ekstensi karakter pelolosan) karena itu akan menjadi perilaku non-standar. Sampai saat ini saya menghabiskan 20+ tahun sebagai spesialis dukungan UNIX. Saya belum pernah mendengar seseorang mengeluh bahwa keberadaan titik dua di direktori yang disematkan di $PATH atau variabel serupa merupakan masalah.

Solusi pilihan saya adalah fungsi seperti splitenv var1 var2 var3

Tidak apa-apa meskipun tidak jelas mengapa (tidak berdokumen) string split tidak cukup. Terlepas dari apakah kita memerlukan fungsi baru, kita pasti tidak boleh menambahkan vars env split otomatis baru. Satu-satunya dua yang cukup umum untuk menjamin perilaku itu adalah PATH dan CDPATH (dan MANPATH karena sudah dalam kasus khusus). Vars lain seperti PYTHONPATH dapat secara eksplisit dibagi oleh pengguna jika mereka merasa berguna.

Namun, setelah mengatakan bahwa pasti harus ada cara untuk mendaftarkan bahwa var tertentu (misalnya, PYTHONPATH) harus memiliki elemen yang digabungkan dengan karakter pemisah tertentu saat diekspor. Cara paling alami untuk melakukan ini adalah melalui opsi baru untuk perintah set . Sebagai contoh,

set -x -S ':' PYTHONPATH dir1 dir2 dir3

Ini tidak akan mempengaruhi bagaimana var disimpan di penyimpanan data var universal di mana char pemisah rekaman akan tetap digunakan dan akan dipisah secara otomatis saat dimuat dari penyimpanan data tersebut. Yang harus ditentukan adalah apakah karakter pemisah terdaftar untuk ekspor juga harus mempengaruhi interpolasi string. Perasaan saya adalah bahwa itu harus. Artinya, jika perintah "set" di atas dijalankan maka perintah berikutnya

echo "PYTHONPATH is $PYTHONPATH"

harus menggunakan titik dua daripada spasi untuk menggabungkan nilai-nilai PYTHONPATH. Pemisah default adalah ruang untuk mempertahankan semantik yang ada dan meminimalkan kejutan bagi pengguna. Perhatikan bahwa vars dengan casing khusus seperti PATH juga akan menggunakan titik dua dalam contoh itu. Yang tidak sesuai dengan perilaku saat ini tetapi konsisten dengan semantik baru dan kurang mengejutkan. Dengan kata lain, mengapa elemen $PATH dipisahkan oleh titik dua di lingkungan yang diekspor tetapi spasi di output

echo "PATH is $PATH"

Perintah string tidak didokumentasikan di mana pun saya dapat menemukan. Juga, man string menunjukkan halaman manual string(3) yang mendokumentasikan fungsi manipulasi string pada BSD (dan Mac OS X).

Tenang, harimau. Ada dalam versi pengembangan - lihat https://github.com/fish-shell/fish-shell/blob/master/doc_src/string.txt

Tidak apa-apa meskipun tidak jelas mengapa pemisahan string (tidak berdokumen) tidak cukup.

Ide awal saya adalah bahwa itu adalah fungsi kenyamanan sehingga operasi ini menjadi benar-benar sepele. Dengan usulan @ridiculousfish itu menjadi sesuatu yang lebih dan menyesuaikan semacam penyimpanan sehingga variabel juga akan bergabung pada karakter itu saat diekspor. string split hanyalah sebuah perintah yang membagi string - pada dasarnya versi cut kami.

Cara paling alami untuk melakukan ini adalah melalui opsi baru untuk perintah set.

Itu pilihan lain, meskipun saya tidak sepenuhnya menjual semantik. Misalnya set -S ':' PYTHONPATH . Apakah itu akan mengatur PYTHONPATH ke daftar kosong atau hanya membagi PYTHONPATH yang ada? Sejauh ini semua opsi yang ditetapkan telah melakukan yang pertama, jadi Anda harus melakukan set -S ':' PYTHONPATH $PYTHONPATH . Atau kami akan membuatnya _not_ melakukan itu dan memiliki inkonsistensi dalam alat yang sama.

Dengan kata lain, mengapa elemen $PATH dipisahkan oleh titik dua di lingkungan yang diekspor tetapi spasi di output echo "PATH is $PATH"

Itu sebenarnya pertanyaan yang bagus. Tentu saja Anda tidak akan mengharapkan pemisah muncul di katakanlah for p in $PATH; echo $p; end , tetapi menggabungkannya dengan karakter pemisah per-variabel mungkin merupakan hal yang benar untuk dilakukan. Tentu saja ada string join untuk melakukannya secara manual.

Perilaku itu, bagaimanapun, mengejutkan. Saya berani bertaruh bahwa jika Anda bertanya kepada 100 orang apa yang terjadi ketika var dengan lebih dari satu elemen diekspor, 90 dari mereka akan mengatakan nilainya digabungkan dengan spasi sebagai pemisah.

Ada masalah umum dengan melakukan desain-demi-survei dan ikan. Karena orang yang disurvei akan sering memiliki pengetahuan tentang bash (dan pada tingkat lebih rendah cangkang POSIXy lainnya) sementara ide ikan adalah melakukan sesuatu _lebih baik_ dengan meninggalkan setidaknya beberapa POSIX.

Itu tidak berarti itu benar-benar tidak berharga, itu hanya sesuatu yang perlu diingat - jika kita berpegang pada ide-ide semacam ini, kita akan memiliki perilaku pemecah kata bash dan if-fi.

Apakah set -S ':' PYTHONPATH akan menyetel PYTHONPATH ke daftar kosong atau hanya membagi PYTHONPATH yang ada?

Itu akan mengaturnya ke daftar kosong. Jika pengguna ingin mempertahankan nilai yang ada, mereka harus memasukkannya secara eksplisit (lihat di bawah).

Kami sudah memiliki semua kemampuan yang diperlukan dengan pengecualian sarana untuk mengkonfigurasi karakter (atau string kosong) untuk digunakan saat menggabungkan elemen array dari var yang diberikan untuk ekspor atau interpolasi. Jika seseorang ingin memanipulasi var seperti PYTHONPATH, mereka dapat memperlakukannya sebagai string sederhana:

set PYTHONPATH "/a/new/dir:$PYTHONPATH"

Atau mereka dapat memperlakukannya sebagai array:

set -S ":" PYTHONPATH /a/new/dir (string split ":" $PYTHONPATH)

Perhatikan bahwa proposal saya untuk menggunakan karakter split/gabungan daripada spasi saat menginterpolasi ke dalam string memberikan perilaku yang konsisten terlepas dari apakah pengguna membagi var ke dalam array atau tidak.

Saya jelas tidak menyarankan desain oleh panitia. Dengan cara itu terletak kegilaan dan kebogoan seperti zsh. Saya hanya menunjukkan bahwa ketika diberikan dua atau lebih opsi tanpa alasan lain untuk memilih satu dari yang lain, maka memilih opsi yang paling tidak akan mengejutkan pengguna shell adalah pilihan terbaik. Itu juga mengapa saya (untuk saat ini) menentang memperkenalkan perintah atau perilaku baru seperti vars pemisah otomatis (selain PATH dan CDPATH, tentu saja). Ini adalah hal yang jarang dilakukan dan biasanya hanya di config.fish dan beberapa fungsi khusus seperti skrip "aktifkan" Anaconda. Dan cara untuk membuat yang terakhir berperilaku dengan benar terlepas dari apakah pengguna telah membagi var ke dalam array di config.fish-nya adalah dengan selalu memperlakukannya sebagai string yang perlu dipisah. Misalnya, jika PYTHONPATH perlu diubah, ia mungkin melakukan sesuatu seperti ini:

# Hypothetical snippet from the Anaconda activate script.
if test (count PYTHONPATH) -gt 1
    set -S ':' PYTHONPATH /activated/python/tree $PYTHONPATH
else
    set PYTHONPATH "/activated/python/tree:$PYTHONPATH"
end

Atau, lebih sederhana,

# Hypothetical snippet from the Anaconda activate script.
set -S ':' PYTHONPATH /activated/python/tree (string split ':' $PYTHONPATH)

Ya, itu berpotensi mengubah string sederhana menjadi array. Tetapi dengan aturan saya bahwa karakter yang ditentukan oleh sakelar -S digunakan saat mengekspor dan menginterpolasi konversi itu ke dalam array seharusnya tidak menjadi masalah dalam praktiknya. Namun, ada satu kasus sudut. Apa yang terjadi jika pengguna belum secara eksplisit mengonversi var ke array di config.fish-nya dan dia kemudian menjalankan sesuatu seperti skrip hipotetis di atas. Var berpotensi menjadi array multi-elemen yang berarti bahwa jika mereka kemudian melakukannya

for elem in $PYTHONPATH
   echo $elem
end

Itu tidak akan mengeksekusi tubuh for loop hanya sekali dengan nilai dalam bentuk direktori yang dipisahkan titik dua seperti yang diharapkan pengguna karena mereka tidak mengetahui pemisahan yang dilakukan oleh skrip "aktifkan" hipotetis. Saya pikir kita bisa hidup dengan itu karena akan jahat bagi pengguna untuk melakukan sesuatu seperti itu.

tl; dr Saya pikir daftar harus "mengingat" pembatasnya dan di bawah ini alasannya.


Saya setuju dengan banyak hal di atas. Satu hal yang masih tampak membosankan adalah bahwa perintah di atas masih tampak terlalu bertele-tele; yaitu, terkadang lebih mudah untuk menjelaskan beberapa perintah ini dalam bahasa Inggris yang sederhana.

Sebagai contoh (dan saya tidak berfokus pada panjang sebanyak pada jumlah hal yang berulang):

  • ikan: set -S ':' PYTHONPATH /activated/python/tree (string split ':' $PYTHONPATH)
  • Bahasa Inggris: "tambahkan /activated/python/tree ke PYTHONPATH ( : -dibatasi`)"

Ada dua hal yang berulang di sini: PYTHONPATH dan pembatas : . Itu PYTHONPATH harus diulang bisa dibilang oke karena dua alasan, dan tak satu pun dari dua alasan ini berlaku untuk pembatas.

  1. Tidak sulit untuk mengetahui apa yang terjadi ketika seseorang mengatakan set PYTHONPATH /activated/python/tree $PYTHONPATH , karena ini sangat mirip dengan hal-hal seperti i = 2 + i , yang merupakan konsep/idiom yang sangat familiar. (Tetapi kami masih memiliki jalan pintas seperti += , itulah sebabnya saya mengusulkan tanda --append di bawah ini.) Di sisi lain, ketika orang berpikir untuk menambahkan ke daftar, mereka tidak berpikir untuk memisahkan dan bergabung pada pembatas. Mereka tidak berpikir untuk mengonversi seluruh daftar ke format lain, melakukan operasi sebenarnya, dan mengembalikannya. Dalam pikiran mereka, mereka secara alami membaca pembatas sebagai pembatas alih-alih mengubahnya menjadi pembatas "internal" atau "pilihan".
  2. Menggunakan perintah set biasa untuk menambahkan menyimpan menambahkan perintah lain untuk menggabungkan dua daftar yang berbeda. Di sisi lain, mengonversi dari satu pembatas ke pembatas lainnya adalah sesuatu yang kami idealnya tidak pernah ingin dilakukan pengguna secara manual, sebagian besar karena alasan di atas.

Sebaliknya, saya menyarankan cara lain untuk menentukan pembatas pada daftar: kaitkan dengan daftar tanpa batas. Jadi contoh di atas mungkin dilakukan sebagai berikut:

# Changes the delimiter for this list. This might be done in some global config file for common lists as this one.
set -S ':' --no-modify PYTHONPATH
# or, workaround if you don't want to add extra options to set:
set -S ':' PYTHONPATH $PYTHONPATH

# The actual append operation
set --prepend PYTHONPATH /activated/python/tree
# or, workaround if you don't want to add extra options to set:
set PYTHONPATH /activated/python/tree $PYTHONPATH

Implikasi/pertanyaan lanjutan/dll:

  1. Ini cukup kompatibel dengan saran saat ini. Berikut adalah perubahan yang diperlukan:

    • Buat tongkat pembatas (mungkin dengan menggunakan variabel lain sebagai __fish_sep_PYTHONPATH )

    • (opsional) Tambahkan tanda yang saat ini saya panggil --no-modify , yang memberi tahu ikan untuk mengubah pembatas daftar tanpa mengubah isinya. Mungkin juga menambahkan flag --append dan --prepend karena alasan (1) di atas. Bagaimanapun yang ini tidak diperlukan, seperti yang ditunjukkan oleh solusi di atas, la bagaimana menambahkan dan menambahkan dilakukan pada ikan hari ini.

  2. Dalam ikan, daftar setidaknya harus _diperlakukan_ seperti warga negara kelas satu. Ini berarti bahwa mengubah pembatas harus mengubah representasi string, bukan representasi daftar (kecuali pembatas ada di salah satu elemen, dalam hal ini pemisahan tidak dapat dihindari). Misalnya, jika Anda mengubah pembatas dari , menjadi : , ["0:1", "2"] harus menjadi ["0", "1", "2"] dan bukan ["0", "1,2"] (yang akan terjadi jika Anda hanya mengubah pembatas tanpa mengubah string yang mendukung daftar). Perilaku ini harus memaksimalkan kompatibilitas dengan perilaku saat ini dan fakta bahwa saat ini ada pembatas default yang tidak dapat diubah.

Inilah intinya:

  • Ini melibatkan lebih sedikit token, dan hampir tidak ada yang diulang.
  • Ini sejajar dengan model mental yang dimiliki banyak pengguna. Pengguna berpikir dalam istilah ini: "tambahkan", "atur pembatas", "jangan ubah".
  • Ini sepertinya satu-satunya cara yang tepat untuk melakukan tugas ini (cara lama sekarang terlihat sangat canggung), sehingga penambahan ini tidak merusak ortogonalitas.
set --no-modify -S : PYTHONPATH
set --prepend PYTHONPATH /activated/python/tree

Terima kasih @szhu , atas komentar mendetail mengenai proposal saya. Namun, ada banyak masalah dengan solusi yang Anda usulkan. Misalnya, penambahan opsi --no-modify sebenarnya mengubah variabel dengan mengubahnya menjadi daftar dan dengan demikian memodifikasi variabel. Meskipun saya menolak hampir semua elemen proposal Anda, hal itu membuat saya berpikir tentang solusi yang lebih mudah yang akan menjawab sebagian besar, jika tidak semua, poin Anda. Mungkin harus ada mekanisme untuk memberi tahu ikan bahwa env var yang diberikan harus selalu secara otomatis dipecah dan disusun kembali pada token yang diberikan (misalnya, ":" atau " "). Ini mungkin disebut penunjukan array otomatis dan ketika dieksekusi, nilai apa pun yang ada akan segera dibagi jika itu belum menjadi array.

Opsi baru dapat ditambahkan ke perintah set untuk mengaktifkan perilaku ini. Namun, saya khawatir melakukan hal itu ambigu dan dapat diartikan sebagai mendefinisikan variabel tanpa nilai. Apakah menambahkan opsi token -A ke perintah set menjadi tidak ambigu? Sebagai contoh:

set -x -A ':' PYTHONPATH

Agaknya itu akan segera mengonversi PYTHONPATH env var yang ada menjadi array setelah dipisah pada titik dua. Sebaliknya akan menghasilkan nilai yang digabungkan pada titik dua saat diekspor atau diinterpolasi ke dalam string. Demikian pula, bahkan jika PYTHONPATH tidak ada pada saat perintah dijalankan, spesifikasi array otomatis akan diingat dan penggunaan selanjutnya akan terpengaruh. Misalnya, ini jelas akan membuat array:

set PYTHONPATH /a/path /b/path /c:/d/path

Tapi bagaimana dengan argumen terakhir itu? Haruskah itu secara otomatis dibagi menjadi dua token?

Perhatikan bahwa perilaku ini hanya berlaku untuk var yang diekspor dan jika tidak, kesalahan akan muncul. Ada juga beberapa kasus sudut yang perlu dijabarkan. Misalnya, bagaimana jika deklarasi auto-split asli menyertakan nilai seperti dalam contoh ini:

set -x -A ':' PYTHONPATH 'hello:goodbye' $PYTHONPATH

Haruskah nilai-nilai itu dibagi pada token pemisahan otomatis? Atau haruskah itu menghasilkan kesalahan dan mengharuskan modifikasi nilai dilakukan dalam pernyataan terpisah? Dan sintaks mana pun yang dipilih, Anda masih memiliki masalah tentang apa yang harus dilakukan tentang nilai yang berisi token auto-split. Iblis ada dalam detailnya. Artinya, mungkin ada konsekuensi lain dari proposal ini yang belum saya pikirkan. Proposal asli saya dengan sintaks yang lebih verbose menghindari masalah itu sejauh yang saya tahu.

@krader1961 , terima kasih atas tanggapan Anda. Namun, Anda tampaknya berpikir bahwa saya mengubah variabel dari string ke daftar. Saya pikir Anda salah memahami satu konsep penting dalam ikan: setiap variabel adalah daftar strings . Variabel yang tampak seperti string sebenarnya adalah daftar dengan panjang 1. ikan memperlakukannya tidak berbeda dengan daftar dengan panjang 0 atau 2 atau panjang lainnya.

Juga, perhatikan bahwa sementara string dasar yang digunakan untuk menyebarkan variabel lingkungan mungkin berubah ketika Anda mengubah pembatas, salah satu keunggulan ikan adalah bahwa pengguna biasanya tidak perlu memikirkan pembatas sama sekali. Inilah mengapa saya merekomendasikan bahwa semua opsi -S adalah menentukan bagaimana daftar ini harus dikonversi menjadi string ketika _diekspor ke luar_ ikan. -S tidak boleh mengubah representasi daftar in-fish (kecuali dalam kasus di mana tidak mungkin untuk merepresentasikan daftar itu menggunakan pembatas target).

Omong-omong, inilah salah satu contoh yang menunjukkan betapa bersihnya proposal saya. Berikut adalah kode untuk mengonversi variabel $L kembali ke pembatas default \x1e . Ini sama sekali tidak akan berpengaruh pada variabel apa pun (ruang lingkup apa pun, sejumlah item apa pun) yang dapat dibuat di ikan hari ini.

set -S \x1e L $L

Satu hal lagi: kelompok argumen --no-modify hanyalah jalan pintas. Berikut adalah padanannya:

| jalan pintas | setara |
| --- | --- |
| set [other args] --no-modify L | set [other args] L $L |
| set [other args] --prepend L $TOADD... | set [other args] L $TOADD... $L |
| set [other args] --append L $TOADD... | set [other args] L $L $TOADD... |

(Saya telah menyatakan yang berikut ini sebelumnya, tetapi saya pikir saya dapat melakukan pekerjaan yang lebih baik untuk menjelaskannya sekarang.) Dengan menekankan betapa "bodohnya" ketiga argumen ini, beberapa orang mungkin mempertanyakan apakah mereka diperlukan sama sekali. Orang dapat menyebutkan bahwa ikan memiliki prinsip desain ortogonalitas . Ketika semua hal ortogonal, ini berarti bahwa untuk tugas besar apa pun yang ingin Anda lakukan, harus jelas set fitur mana yang harus dipilih untuk melakukan tugas itu -- seharusnya hanya ada satu cara yang benar untuk melakukannya. Di sini, saya memang menambahkan cara lain untuk menambahkan ke/menambahkan ke/mencegah modifikasi ke daftar, tetapi ini hanya karena saya pikir padanan yang diganti tidak perlu bertele-tele; mereka seharusnya bukan cara yang tepat untuk menambahkan daftar modifikasi. Salah satu cara untuk meyakinkan diri Anda tentang hal ini adalah dengan memikirkan bagaimana Anda berpikir untuk menambahkan ke daftar. Anda mungkin berpikir "tambahkan $TOADD ke $L " daripada "set $L ke $L $TOADD ".

Beri tahu saya apa pendapat Anda, dan jika ini membuat kasus yang lebih meyakinkan untuk proposal saya. (Juga cukup umum bagi saya untuk salah paham, jadi jangan ragu untuk mengoreksi saya.)

@szhu Saya cukup sadar bahwa semua vars dalam ikan adalah daftar nilai nol, satu, atau lebih. Anda juga tampaknya tidak membaca komentar saya sebelumnya di mana saya dengan jelas menyatakan bahwa pembatas terkait tidak boleh memengaruhi representasi internal atau bagaimana nilai dipertahankan ke penyimpanan data universal (selain menyimpan pembatas). Anda juga tidak membahas poin saya sebelumnya. Pertimbangkan contoh terakhir Anda:

set -S \x1e L $L

Apa yang harus dilakukan jika L sudah berisi dua atau lebih nilai? Agaknya tidak ada yang lain selain mengubah pembatas terkait. Akankah argumen $L menjadi opsional dalam kasus itu? Atau haruskah terlebih dahulu mengubah array yang ada menjadi string sederhana (mungkin digabungkan menggunakan pembatas yang ada) kemudian membagi string itu pada pembatas baru? Seperti yang saya katakan sebelumnya, iblis ada dalam detailnya.

Pada akhirnya perancang dan pengelola yang mapan akan memutuskan apakah keluarga fungsi --no-modify Anda harus ditambahkan atau tidak, tetapi saya memilih tidak karena mereka tidak menambahkan nilai yang cukup menurut pendapat saya relatif terhadap biayanya.

Maaf, utas ini panjang, saya pasti melewatkan pengakuan Anda tentang ini di atas; senang mengetahui kita berada di halaman yang sama! Saya pikir saya telah mengatasi sebagian besar kekhawatiran Anda di atas juga, tetapi tidak semuanya. Saya akan secara khusus mengatasi setiap masalah Anda di bawah ini.


1. Apakah $L opsional dalam set -S \x1e L $L ?

Perilaku set yang ada tidak akan berubah. Di bawah perilaku saat ini, set L $L tidak mengubah L dan set L membuat L menjadi daftar kosong. Sama dengan set -S \x1e L $L dan set -S \x1e L .

1.1 Bukankah set -S \x1e L $L tampak terlalu bertele-tele hanya dengan mengubah pembatas?

Agak. Itu sebabnya saya mengusulkan opsi --no-modify sebagai jalan pintas untuk ini.

Tapi rencana saya tidak akan berantakan jika jalan pintas ini tidak ada. Kami sudah menangani masalah ini setiap hari ketika kami menambahkan daftar: set PATH ~/.bin $PATH . Itu sebabnya, untuk alasan yang sama, saya mengusulkan --prepend dan --append juga.

2. Bagaimana proses konversi berlangsung?

Katakanlah pembatas lama kita adalah \x1e dan pembatas baru kita adalah : , dan kita memiliki daftar ikan ["hello", "world"] (diekspor sebagai hello\x1eworld ). Ada dua cara dasar untuk melakukan konversi (" pilihan konversi "):

  1. Gunakan ["hello", "world"] dan ubah menjadi ["hello", "world"] (diekspor sebagai hello,world )
    Keuntungan: Representasi daftar tidak berubah.
  2. Gunakan hello\x1eworld dan ubah menjadi ["hello\x1eworld"] (diekspor sebagai hello\x1eworld )
    Keuntungan: Representasi nilai yang diekspor tidak berubah.

Perhatikan bahwa ini dari perspektif UI, bukan perspektif implementasi; kita berbicara tentang seperti apa tampilannya bagi pengguna. Saya akan membahas implementasi di pertanyaan berikutnya. _Catatan: sisa jawaban ini adalah hal baru yang belum saya bahas di atas, didorong oleh pertanyaan Anda. Terima kasih!_

Di dalam ikan. Pertama, jika kita bekerja sepenuhnya di bidang ikan, daftar adalah kelas satu dan Anda tidak perlu khawatir tentang pembatas, jadi keduanya tidak diperlukan. (Sekali lagi, "harus" adalah dari sudut pandang pengguna, sebagai pengembang, adalah tanggung jawab kami untuk mewujudkannya.)

Mengubah format ekspor vars. Jadi, satu-satunya alasan pengguna perlu mengubah pembatas adalah untuk mengubah string yang diekspor untuk program yang membaca variabel lingkungan. Untuk list yang dibuat di fish, kita pasti akan menggunakan opsi konversi 1 , karena arti variabel sebagai list penting dan terdefinisi dengan baik, jadi kita perlu mempertahankan representasi list.

Mengubah format impor vars. Namun, untuk variabel lingkungan seperti PATH yang awalnya dibuat di luar ikan, kita perlu, untuk daftar yang sudah memiliki pembatas, memberi tahu ikan apa pembatas itu. Untuk ini kita dapat menggunakan opsi konversi 2 .

2.1 Bagaimana ini akan diterapkan?

Ikan meskipun pengguna tidak perlu mengetahui hal ini, ikan sebenarnya menyimpan daftar sebagai string. Variabel x disimpan sebagai hello\x1eworld . Di bawah proposal saya, akan ada variabel lain, __fish_delimiter_x , yang menentukan pembatas variabel x . Itu tidak ada sekarang dan jadi kami menggunakan pembatas default, \x1e .

Untuk opsi konversi 1:

  1. Pisahkan variabel pada pembatas lama, menghasilkan daftar yang benar dalam bahasa implementasi (C++).
  2. Bergabunglah dengan daftar menggunakan pembatas baru, menghasilkan string baru.
  3. Simpan pembatas baru ke __fish_delimiter_x .

Untuk opsi konversi 1, implementasi yang setara:

  1. Dalam variabel, ganti semua kemunculan pembatas lama dengan yang baru.
  2. Simpan pembatas baru ke __fish_delimiter_x .

Untuk opsi konversi 2:

  1. Simpan pembatas baru ke __fish_delimiter_x .

2.2 Jika kita membutuhkan kedua opsi konversi, bagaimana pengguna menentukan mana yang akan digunakan?

Mungkin kita dapat memiliki dua opsi: -D atau --convert-delimiter untuk opsi 1 dan -d atau --set-delimiter untuk opsi 2.

2.3 Apakah kita benar-benar membutuhkan kedua opsi tersebut?

Di bawah ikan saat ini, kami memilih untuk berasumsi bahwa kami tidak akan melihat \x1e di alam liar di luar ikan. Jika kita mempertahankan ini sebagai pembatas default dan mempertahankan asumsi ini, opsi konversi 1 cukup untuk mengonversi dan menyetel pembatas dan kita tidak memerlukan opsi konversi 2 . (Cara mudah untuk memastikan hal ini adalah dengan menyadari bahwa jika asumsinya benar, saat mengonversi daftar yang dibuat secara eksternal, langkah konversi opsi 1 "ganti semua kemunculan pembatas lama dengan yang baru" tidak akan menghasilkan apa-apa, mengurangi seluruh konversi ke opsi konversi 2.)


@ridiculousfish , saya akan menghargai umpan balik Anda tentang ini juga, khususnya mengenai UI dan detail implementasi. Terima kasih!

Tampaknya ada dua masalah di sini. Langsung saja kita bahas yang pertama?

+1 untuk array yang benar

Apakah trik pemisah itu benar-benar diperlukan untuk ikan? Ping #627

Meninjau kembali ini sehubungan dengan perbaikan saya untuk masalah #2106 di mana saya perhatikan ada dua cara yang tidak kompatibel untuk mengubah representasi string untuk nilai variabel menjadi array. Salah satunya salah menghilangkan elemen kosong. Masalah intinya adalah bahwa class env_var_t didasarkan pada wcstring daripada vektor wcstring. Apakah perubahan itu sepadan atau tidak, masih bisa diperdebatkan.

Jika Anda mengikuti masalah ini, saya mendorong Anda untuk melihat, dan mungkin menguji, PR #4082. Saya memutuskan cara terbaik untuk mengatasi ini adalah variabel "terikat" yang mirip dengan fitur dengan nama yang sama di zsh.

Sepertinya pertanyaan seputar daftar yang diekspor titik dua ini dan envvar apa yang harus dimasukkan dalam daftar putih ini, adalah sesuatu yang belum diputuskan. Apa status saat ini tentang masalah ini? Bisakah kita mengharapkan solusi akhir untuk topik ini? Baru hari ini, saya kembali mengalami jebakan bahwa LD_LIBRARY_PATH tidak ada dalam daftar putih...

Untuk meringkas: Variabel lingkungan Unix adalah string, jadi env vars seperti array harus menggunakan pembatas. Sebagian besar menggunakan titik dua ($PATH); meskipun tidak semua melakukannya ($LESS). Kami hanya ingin menggunakan titik dua untuk membatasi semua array pada impor/ekspor (dan memang ikan dulu bekerja dengan cara ini); masalahnya adalah beberapa variabel datar mengandung titik dua ($DISPLAY, $SSH_CONNECTION).

Tujuannya adalah untuk membuat variabel yang dibatasi bekerja secara alami dengan dukungan array ikan. @szhu menyarankan meningkatkan set untuk melacak pembatas, tetapi peningkatan IMO set adalah tempat yang salah untuk melampirkan ini:

  • Interaksi yang mengganggu antara menyetel variabel dan menyetel pembatasnya (memotivasi --no-modify ).
  • Pertanyaan rumit seputar bagaimana pembatas berinteraksi dengan cakupan variabel.
  • Masalah seputar variabel universal. Kita harus mengajari uvars untuk mengingat pembatas, dan juga tentang --no-modify karena tidak ada cara untuk menyetel variabel ke nilai saat ini dengan uvars.

Pada ulasan saya menyukai ide splitenv @faho . splitenv name akan membagi variabel yang ada pada titik dua, itu saja. Ini sangat sederhana. Variabel yang tidak menggunakan titik dua cukup langka sehingga kita tidak memerlukan dukungan khusus untuk variabel tersebut.

Kelemahannya adalah bahwa array yang diekspor ikan akan diimpor kembali sebagai string yang dipisahkan titik dua; dalam praktiknya saya pikir ini akan jarang terjadi.

Kami seharusnya tidak menimbulkan komplikasi splitenv ini pada pengguna jika kami dapat menghindarinya. Jadi saya ingin melangkah lebih jauh, dan memperluas daftar putih titik dua ke semua variabel lingkungan yang namanya berakhiran PATH , misalnya LD_LIBRARY_PATH, PYTHONPATH, dll. Dalam praktiknya ini harus melakukan hal yang benar hampir sepanjang waktu; siapa pun yang digigitnya dapat menggunakan string join untuk memperbaiki nilainya.

Jadi apa yang saya usulkan (proposal yang benar-benar faho):

  • Ekspor semua array menggunakan titik dua; tidak ada lagi pemisah catatan ASCII.
  • Menerapkan fungsi splitenv yang membagi variabel pada titik dua. Ini dapat ditulis dalam skrip ikan.
  • Tingkatkan daftar putih yang dipisahkan titik dua untuk semua variabel yang diakhiri dengan PATH.

Saya percaya ini akan mengatasi sebagian besar rasa sakit yang terkait dengan array yang dibatasi titik dua dengan cara yang minimalis dan kompatibel.

mengenai ide splitenv:

Katakanlah saya ingin ikan mengekspor daftar yang itemnya berisi titik dua, misalnya: ["item1", "item:2"] . (Saya tidak berpikir ini adalah kejadian langka, terutama ketika array digunakan untuk menyimpan input pengguna.)

Apakah daftar akan diekspor sebagai item1:item:2 ? Jika demikian, tidak mungkin membuat ulang daftar asli setelah ekspor.

Juga, memiliki daftar putih yang tidak dapat diubah untuk variabel terasa salah, meskipun memiliki daftar putih menjadi *?PATH terasa kurang salah. (Itu adalah alasan lain untuk proposal saya untuk menyimpan pembatas sebagai variabel -- daftar putih dapat diubah dengan menyetel variabel.)

@szhu Anda benar. Exported-lists-can't-contain-colons adalah masalah yang dialami Unix:

Sejak \

jadi saya tidak merasa terlalu buruk untuk memperkenalkan batasan yang sama untuk ikan (hanya untuk variabel yang diekspor).

Juga masalah ini hanya terjadi ketika mengekspor array ke instance ikan yang dipanggil secara rekursif, yang menurut saya akan jarang terjadi. Jika ini terbukti umum, kita bisa melampirkan data sespan di variabel lain, atau menggunakan pemisah array yang berbeda saat memanggil ikan secara rekursif. Dugaan saya adalah kita tidak perlu pergi sejauh itu.

Saya setuju bahwa kasus tepi di mana proposal tidak berfungsi dengan baik tidak terlalu umum, tetapi saya khawatir akan sangat buruk jika orang mengalaminya.

Berikut adalah contoh yang hanya dibuat-buat sebagian:

set -x TEST color:red 
set -x TEST2 color:red font:serif
set -x TEST_PATH color:red 
set -x TEST2_PATH color:red font:serif
exec fish
echo $TEST #=> color:red
echo $TEST2 #=> color:red:font:serif
echo $TEST_PATH #=> color red 
echo $TEST2_PATH #=> color red font serif

Saya bisa membayangkan banyak pengguna baru yang bingung setelah mengamati hal di atas.

Saya pikir perilaku berikut akan jauh lebih menyenangkan:

set -x TEST color:red 
set -x TEST2 color:red font:serif
set -x TEST_PATH color:red 
set -x TEST2_PATH color:red font:serif
exec fish
echo $TEST # color:red
echo $TEST2 # color:red font:serif
echo $TEST_PATH #=> color:red 
echo $TEST2_PATH #=> color:red font:serif

Saya ingin pendapat Anda dan komunitas tentang yang satu ini.

Mengapa tidak keluar dari titik dua yang ada? Itu akan menjaga perbedaan.

Melarikan diri masuk akal bagiku.

Mungkinkah masih membingungkan bahwa apakah suatu variabel adalah array tidak akan diingat?

set -x TEST2 color:red font:serif
set -x TEST2_PATH color:red font:serif
exec fish
echo $TEST2 # color\:red:font\:serif
echo $TEST2_PATH #=> color:red font:serif

Ya. Hipotesis saya adalah bahwa mengekspor array tidak umum, di luar daftar jalur.

MANPATH memiliki arti khusus untuk titik dua ganda (::) - lihat #2090 - apakah ini berhasil?

Saya juga berpendapat bahwa memiliki variabel sespan FISH_ARRAY_VARIABLES=FOO\t:\nBAR\t;\nBAZ\t-\n dalam hal apa pun akan menjadi petunjuk yang baik untuk contoh Fish dipanggil untuk mengambil variabel array lagi, tanpa mengganggu proses lain dan tanpa memerlukan "kami melibatkan ikan sekarang" pemeriksa..

re: https://github.com/fish-shell/fish-shell/issues/436#issuecomment -392409659 @zanchey
Saya belum membaca #2090 secara detail, tetapi saya yakin konversi antara string yang dibatasi titik dua dan bentuk array benar-benar mulus (kecuali ketika titik dua ~tidak muncul~ muncul dalam item array).

Untuk memasukkan titik dua ganda di MANPATH , cukup tambahkan string kosong di mana titik dua ganda akan muncul:

$ set -x MANPATH 1 2 '' 3
# Check if it's set
$ bash -c 'echo $MANPATH'
1:2::3

Untuk memulai MANPATH dengan titik dua, cukup tambahkan item string kosong di awal:

$ set -x MANPATH '' 1 2 3
# Check if it's set
$ bash -c 'echo $MANPATH'
:1:2:3

Saya belum mengikuti semuanya di sini, tetapi sebagai pengguna saya ingin menganjurkan "tidak ada konfigurasi".
Saya pikir set -S dan splitenv adalah bentuk konfigurasi. Beberapa pengguna akan melakukannya di fish.config dan menangani PYTHONPATH sebagai array. Yang lain tidak akan dan menangani PYTHONPATH sebagai kata yang dibatasi titik dua tunggal. Salin-tempel saran stackoverflow dan menjalankan skrip yang memanipulasi PYTHONPATH dari satu pengguna ke pengguna lain tidak akan selalu berhasil...

Aturan tetap "jika diakhiri dengan PATH " bebas konfigurasi dan terdengar sesempurna yang Anda bisa dapatkan :+1:
(Saya tidak punya pendapat tentang apakah itu sepadan dengan ketidakcocokan ke belakang)
Ya, set -x TEST2_PATH color:red font:serif akan diimpor sebagai array color red font serif tetapi itulah masalahnya dengan mengekspor variabel. Anda tidak dapat benar-benar mengatur var yang diekspor ke array tanpa memahami cara kerjanya.

Ya. Hipotesis saya adalah bahwa mengekspor array tidak umum, di luar daftar jalur.

@ridiculousfish yang mungkin benar dalam cangkang saat ini, tetapi saya membayangkan bahwa ketika ikan mendapatkan lebih banyak daya tarik, pengguna mungkin ingin memanfaatkan kemampuan ikan untuk mengirim daftar ke cangkang ikan anak. Saya dapat membayangkan pada akhirnya mungkin ada program/plugin yang mengelola status sesi ikan (saya akan memeriksa kembali komentar ini dalam beberapa tahun untuk melihat apakah ini benar), dan dapat secara universal melakukan de/serialize daftar akan membuat kode itu lebih bersih dan lebih sedikit solusi-y.


Semacam pemikiran yang mirip tetapi sedikit berbeda: Memperlakukan PATH sebagai kasus khusus adalah kasus tepi anakronistik yang mungkin dipahami pengguna hanya jika mereka memiliki riwayat pada kasus penggunaan umum shell. Ini membatasi kemampuan ikan untuk digunakan sebagai bahasa skrip umum, dan membatasi beberapa kasus penggunaan potensial di masa mendatang.

@ridiculousfish Saya pikir salah satu solusi yang mungkin adalah mengaitkan setiap variabel/array lingkungan dengan pemisahnya sendiri (dan Anda dapat menyimpan '\x1e' atau ' ' atau ':' sebagai default), dan pengguna yang membuat variabel lingkungan bertanggung jawab untuk memilih pemisah yang sesuai untuk menghindari konflik. Perintahnya mungkin seperti: set --separator ':' TMP 1 2 3 . Jadi untuk variabel lingkungan yang terkenal itu, pengguna cukup memilih pemisah terkenal yang sesuai yang juga dapat dikenali oleh program lain dan dapat membuat ikan lebih kompatibel dengan lebih banyak program (seperti Python).

Bagi mereka yang hanya membaca komentar terbaru, perhatikan bahwa rekomendasi set --separator @thuzhf sama dengan rekomendasi set -S yang disebutkan berulang kali di seluruh utas ini. Untuk mendapatkan lebih banyak konteks pada diskusi itu, Anda dapat mengambil halaman ini untuk set -S .

@szhu Maaf karena tidak memperhatikan set -S sebelumnya. Itu pada dasarnya yang saya inginkan juga. Saya juga memperhatikan bahwa ada beberapa kekhawatiran yang dimiliki orang lain tentang opsi baru ini. Saya dapat memberikan pemikiran saya tentang masalah ini di bawah ini (karena set ikan belum menggunakan -s sebagai opsi, saya akan menggunakan -s untuk merujuk ke --separator selanjutnya):

  1. --no-modify memang mengubah sesuatu. Ya, dan Anda harus mengubah namanya menjadi eksplisit, misalnya --change-separator .
  2. Ada beberapa kasus sudut/rumit. Ini pada dasarnya disebabkan oleh sintaks yang tidak terdefinisi dengan baik, dan dapat dihindari secara alami jika kita memberikan definisi sintaks yang ketat. Sebagai contoh:

    1. Ide dasar: setiap var (daftar) dikaitkan dengan pemisahnya sendiri ketika didefinisikan (defaultnya adalah ' ' ). Pemisah ini akan digunakan ketika var ini dibuat dari string dan ketika diubah menjadi string (ini adalah ide umum dalam beberapa bahasa seperti fungsi join() Python). Sebuah var dikonversi menjadi string saat diekspor atau saat pengguna ingin melakukan ini.

    2. Cara membuat env vars



      1. set ENV_VAR a b c . Tanpa -s , kami memilih ' ' sebagai pemisah default.


      2. set -s ':' ENV_VAR . Dalam hal ini, ENV_VAR diatur menjadi daftar kosong.


      3. set -s ':' ENV_VAR a b:c d e:f . Dalam hal ini, pengguna yang menulis kode ini harus memahami dengan jelas bahwa ':' adalah pemisah dan memahami ENV_VAR akan menjadi array seperti ['a b', 'c d e', 'f'] dan akan diekspor sebagai 'a b:c d e:f' . Bagaimana jika Anda ingin ENV_VAR yang diekspor dimulai dengan spasi dan diakhiri dengan spasi? Anda harus menggunakan escape seperti: set -s ':' ENV_VAR \ a b:c d e:f\ . Kemudian ENV_VAR akan menjadi [' a b', 'c d e', 'f '] dan akan diekspor sebagai ' a b:c d e:f ' .


      4. set -s ':' ENV_VAR a b:c d e:f $ENV_VAR . Dalam hal ini, itu tergantung pada cara kerja $ . Jika didefinisikan sebagai mengekstrak nilai string ENV_VAR alih-alih daftar, maka perintah ini akan sama dengan hanya mengganti $ENV_VAR dengan nilai string yang dikonversi dari daftar di bawahnya, dan dalam hal ini, set -s ':' ENV_VAR a b:c d e:f:$ENV_VAR adalah mungkin yang Anda inginkan (perhatikan : setelah f ); jika didefinisikan sebagai mengekstraksi variabel ENV_VAR (yang merupakan daftar alih-alih string), maka ini harus menjadi operasi perluasan daftar seperti pada python. Misalnya, dalam kasus terakhir, jika ENV_VAR adalah ['x', 'y'] sebelumnya, maka setelah operasi ini ENV_VAR akan menjadi ['a b', 'c d e', 'f', 'x', 'y'] . Bagaimana jika pemisah ENV_VAR sebelumnya bukan ':' ? Dalam kasus sebelumnya, Anda bertanggung jawab untuk memastikan Anda melakukan hal yang benar, misalnya, Anda mungkin harus menggunakan pemisah yang konsisten dengan mengubah pemisah asli menjadi ':' atau dengan mengubah pemisah saat ini menjadi yang asli. Dalam kasus terakhir, ini akan mengatur pemisah array ini dari yang asli (tidak peduli apa itu) menjadi ':' .



    3. Bagaimana mengubah pemisah



      1. set --change-separator ':' ENV_VAR . Jika ENV_VAR tidak ada, program harus keluar dengan kode kesalahan selain 0. Cukup mudah dan eksplisit.



    4. Cara melihat pemisah



      1. set --view-separator ENV_VAR .



Selain itu, saya benar-benar berpikir masalah ini sudah jelas dan mendesak dan merupakan masalah besar bagi pengguna dan berharap masalah ini dapat diselesaikan sesegera mungkin karena ini sangat memengaruhi pengalaman pengguna. Sebenarnya saya belum menemukan masalah lain (bahkan sangat kecil) untuk saat ini menggunakan ikan kecuali yang sangat besar ini.

Saya benar-benar berpikir masalah ini sudah jelas dan mendesak

@thuzhf : Saya akan mengatakan Anda melebih-lebihkan itu.

Salah satu alasannya adalah bahwa masalah Anda di #5169 adalah dengan $LD_LIBRARY_PATH, tetapi itu sebenarnya bukan daftar di ikan! Anda harus mengaturnya seperti set LD_LIBRARY_PATH "$LD_LIBRARY_PATH:/some/path" , seperti di shell lainnya.

Fish mengubah tepat tiga variabel yang diwarisi/diekspor ke dalam daftar secara otomatis:

$PATH, $MANPATH dan $CDPATH. Dan tepatnya daftar ini akan memiliki pemisah ":" saat diekspor.

Variabel "standar" lainnya seperti $LD_LIBRARY_PATH tidak boleh ditangani sebagai daftar dalam skrip ikan, jadi Anda tidak mengalami masalah ini. Variabel yang tidak terstandarisasi dapat Anda tangani sesuka Anda, karena program lain tidak akan melakukan apa pun dengannya, jadi pemisahnya tidak kritis.

@faho Terima kasih atas penjelasan Anda yang jelas. Itu sangat masuk akal bagi saya. OK, saya dapat mengatakan masalah ini terpecahkan untuk saya.

Saya melihat masalah MANPATH yang dijelaskan di #2090. Skenarionya adalah menambahkan manpath sedemikian rupa sehingga terus menggunakan jalur sistem.

Dalam bash seseorang akan menulis ini sebagai export MANPATH="$MANPATH:/new/path" . Jika MANPATH disetel, ini akan ditambahkan ke dalamnya. Jika tidak disetel, ini akan menambahkan titik dua, yang merupakan indikasi khusus pria untuk menggunakan direktori sistem. Sintaks ini tidak bekerja pada ikan; masalahnya adalah MANPATH adalah array dan "$MANPATH" akan memiliki spasi, bukan titik dua.

Pendekatan "variabel terikat" akan memungkinkan kita untuk memiliki misalnya fish_manpath sebagai larik yang mencerminkan MANPATH sebagai string yang dipisahkan titik dua. Ini bisa dibangun sepenuhnya dalam skrip ikan. Namun kami ingin melakukan ini untuk semua variabel seperti jalur, bukan hanya MANPATH, dan itu akan menjadi pemutusan kompatibilitas yang signifikan yang tidak jelas bagaimana cara mengelolanya. Juga memiliki masalah yang sama, misalnya variabel array manpath di zsh canggung untuk ditambahkan, jadi tidak jelas mengapa itu ada.

Proposal saya di sini tidak membuat situasi MANPATH lebih baik atau lebih buruk; Saya pikir hal yang harus dilakukan adalah menyepak bola dan hanya memiliki cerita yang mudah untuk ditambahkan ke MANPATH, yaitu ini:

set -q MANPATH || set MANPATH ''
set -x MANPATH $MANPATH /new/path

Itu tidak terlalu menyakitkan untuk ditempelkan ke config.fish.

Proposal saya di sini tidak membuat situasi MANPATH lebih baik atau lebih buruk; Saya pikir hal yang harus dilakukan adalah menyepak bola dan hanya memiliki cerita yang mudah untuk ditambahkan ke MANPATH, yaitu ini:

@ridiculousfish : Saya telah berpikir untuk melangkah lebih jauh, sebenarnya: Pisahkan variabel khusus ini pada ":" juga pada tugas, dan gabungkan dengan ":" alih-alih spasi dalam ekspansi yang dikutip.

Itu berarti ketika Anda melakukan set -gx MANPATH "$MANPATH:/new/path" , ikan pergi dan melakukan pemisahan secara otomatis, menghasilkan setara dengan set -gx MANPATH "" /new/path .

Sekarang, ini berarti bahwa ":" tidak dapat muncul di jalur di $MANPATH (dan $PATH, dan $CDPATH), tetapi mereka tetap tidak dapat melakukannya karena akan merusak utilitas non-ikan!

Itu juga akan memungkinkan kami untuk suatu hari menghapus penanganan khusus, karena itu menambahkan cara penanganan yang kompatibel-silang - Anda hanya perlu menetapkan dengan : , dan menggunakannya dengan (string split : -- $MANPATH) , dan itu akan berfungsi bahkan jika penanganan itu dihapus.

@faho Saya menerima gagasan itu - bagaimana pengguna menandai variabel sebagai menerima perlakuan khusus ini? Akankah splitenv melakukannya?

bagaimana pengguna menandai variabel sebagai menerima perlakuan khusus ini?

Ide saya sebenarnya adalah untuk tidak mengizinkan penandaan sama sekali - biarkan saja sebagai perilaku khusus untuk $PATH et al. Yang akan membuat kita menjauh dari daftar di beberapa titik di masa depan.

Namun, sejak itu saya mulai memahami bahwa mengizinkan ini untuk variabel lain juga membantu kami dengan variabel lain - misalnya saya telah mengatakan sebelumnya bahwa $EDITOR saya disetel sebagai satu elemen ( set EDITOR "emacs -nw" ) untuk kompatibilitas dengan eksternal alat, tetapi ikan lebih suka jika itu daftar.

Jadi saya mungkin akan default ke _space_ sebagai pembatas, kecuali itu seperti PATH (dan dengan asumsi bahwa jika namanya diakhiri dengan PATH mungkin baik-baik saja).

Apakah splitenv akan melakukannya?

Saya tidak terlalu suka memperkenalkan builtin lain untuk ini, jadi saya mungkin akan menggunakan opsi argument-to-set.

Saya setuju bahwa "PATH/MANPATH/CDPATH dengan casing khusus itu aneh; kami membutuhkan solusi yang lebih umum".

Saya mengusulkan agar kita BERHENTI PATH/MANPATH/CDPATH casing khusus. Mereka akan diperlakukan (oleh pengguna akhir ikan) sebagaimana mereka berada di cangkang lainnya. $PATH (dan yang lainnya) akan menjadi string tunggal (atau dalam jargon ikan daftar dengan panjang 1) dengan titik dua di dalamnya. Perhatikan bahwa saya mengacu pada pengalaman pengguna ikan, bukan bagaimana hal-hal ini ditangani secara internal; Saya tidak tahu seperti apa implementasi di dalam ikan--saya mengandalkan orang lain untuk menunjukkan masalah apa pun di sana.

Memang, itu akan memiliki kelemahan dari ketidakcocokan ke belakang, tapi saya pikir itu akan sangat berharga sebagai keuntungan besar dalam kesederhanaan dan keanggunan. Saya pikir itu akan membahas #2090 juga.

Apa yang semua orang pikirkan?

5245 telah digabungkan, jadi ini sepertinya terpecahkan.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat