LINUX.ORG.RU

Lua Shell

 , , ,


2

6

Контест этого топика: Леннарт теперь до эмуляторов терминала добрался (комментарий)

@EXL:

Лучше бы Lennart взялся за Bash.

@wandrien:

Там только выкинуть целиком. Я вот хочу попытаться для lua сделать обвязку для скриптинга уровня оболочки. Подобные либы на Lua есть, но качество и объем фич мне не нравится. Надо лучше. Тебе бы был интересен такой проект?


Итак, вот моя идея в общих чертах. Составные части, на которых основываться:

https://github.com/BanceDev/lush
Низкое качество сборочного скрипта. Вероятно, и кода тоже. Интересует идея в первую очередь.

https://github.com/mna/luashell
Ключевое, что нам нужно. Взять за основу. Но:

  • Нужны полнофункциональные средства перенаправления ввода-вывода, заменить эту часть API. Под капотом, вероятно. придётся делать полноценную обработку fork - настройка процесса - exec.
  • test() должен быть вменяемый, а не парсить строку по пробелам. Просто алиас для sh.cmd("test", ...).exec()
  • Форк процесса без exec в качестве элемента пайплайна на уровне API
  • Как расширение предыдущего - обёртка а ля sh.echo("text").

В качестве базового API взять https://25thandclement.com/~william/projects/lunix.html вместо https://github.com/luaposix/luaposix

Также рассмотреть для включения и/или как источник идей:


Общая идея:

  • Lua + lunix — получаем возможность писать на Луа «приложения как на Си под libc».
  • Сверху на это - форкнутый и допиленный luashell. Это ключевое.
  • Далее QoL вещи: lua-path, argparse, функции для парсинга и форматирвоания времени, функции для JSON.
  • Далее - разработать интерактивный режим для использования в качестве командной оболочки.

Продукт компилируется в статический бинарь с musl и/или cosmopolitan libc и получаем «вечный» shell. При этом весьма компактный.

★★★

Последнее исправление: wandrien (всего исправлений: 4)
Ответ на: комментарий от papin-aziat

То есть ты делаешь Pathname Expansion и удивляешься, что Pathname Expansion работает как положено?

Вот поэтому и нужны кавычки, которые выше обсуждали. Чтобы не получалось с «вдруг в рабочем каталоге что-то».

wandrien ★★★
() автор топика
Ответ на: комментарий от wandrien

cmd(‘gunzip’).in(‘file.gz’).to(‘xz’).out(‘file.xz’).exec()

А потом эти же самые люди этими же самыми губами ругают лисп за то, что в нём много скобачек.

Nervous ★★★★★
()
Ответ на: комментарий от Nervous

А потом эти же самые люди этими же самыми губами ругают лисп за то, что в нём много скобачек.

Я как-то не в настроении сегодня, чтобы пытаться вежливо отвечать на идиотские комменты.

wandrien ★★★
() автор топика
Ответ на: комментарий от wandrien

Таких случаев всё равно должно быть немного, но их надо помнить. Память у башиста должна быть как у лгуна 😁

papin-aziat ★★★★★
()
Ответ на: комментарий от Nervous

Просто оставьте шеллу шеллово — выполнение команд и их комбинирование в более сложные команды, а сами команды пешите на чём угодно, только не на шелле.

А управление «выполнением команд и их комбинированием в более сложные команды» на чем писать?

wandrien ★★★
() автор топика
Ответ на: комментарий от wandrien

То, что у нас всех массово синдром утёнка относительно sh, не делает sh хорошим языком.

Он отвратителен как язык программирования, такое могло родиться и выжить только в атмосфере полного отсутствия альтернатив — другой скриптухи просто не было.

И в то же самое время он вполне себе удобен и хорош как интерпретатор команд.

Nervous ★★★★★
()
Ответ на: комментарий от Nervous

И в то же самое время он вполне себе удобен и хорош как интерпретатор команд.

Да, пока там две с половиной команды и полтора перенаправления. чо-то там | sort | uniq -c. На этом полномочия всё.

wandrien ★★★
() автор топика
Ответ на: комментарий от wandrien

Собственно, очень часто этого и достаточно. Если нужна какая-то более сложная логика, лучше обернуть её в команду, написанную на нормальном языке.

Nervous ★★★★★
()
Ответ на: комментарий от papin-aziat
  1. По возможности не пишите ни на какой разновидности sh.
  2. Если пишете на любой разновидности sh, то пользуйтесь линтером, строго соблюдайте правила по квотированию всего подряд и выучите best practices.
wandrien ★★★
() автор топика
Ответ на: комментарий от wandrien

строго соблюдайте правила по квотированию всего подряд и выучите best practices

Это для профессионалов. Мне интересно разобраться.

papin-aziat ★★★★★
()
Ответ на: комментарий от wandrien

Вот поэтому и создана эта ветка про допил набора библиотек для нормального языка.

Вот это уже другое дело — а то «давайте напишем свой баш, с метатаблицами и индексацией с единицы». Собрать в кучу батарейки для более удобного напесания команд — уже похоже на рабочий план.

Хотя я, конечно, не очень понимаю, зачем, если уже есть бабашка с целым железнодорожным составом батареек %)

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от wandrien

То есть ты делаешь Pathname Expansion и удивляешься, что Pathname Expansion работает как положено?

Нет, я делал то, что делал, и на мой взгляд это тупо омонимия (хотя, может быть где-нибудь на просторах башевого мана об этом сказано. Не читал). Так что это походу прекрасный пример того, к чему твоя претензия 🙂

papin-aziat ★★★★★
()
Ответ на: комментарий от papin-aziat

и на мой взгляд это тупо омонимия

Прекрасный язык, да?

Они улучшили sh в bash, но от этого легче не стало.

wandrien ★★★
() автор топика
Ответ на: комментарий от Nervous

он вполне себе удобен и хорош как интерпретатор команд

А что, если запилить обёртку над sh, которая будет падать с сообщением типа this feature is deprecated при попытке использовать его как язык программирования — условия там, циклы и всё такое прочее. Сделаем sh интерпретатором команд снова!

А потом переписать его на Rust, конечно — выкинув по дороге весь этот deprecated. Даже интересно, насколько он похудеет.

Nervous ★★★★★
()
Ответ на: комментарий от Nervous

Он отвратителен как язык программирования … И в то же самое время он вполне себе удобен и хорош как интерпретатор команд.

Теперь попробуйте совместить, чтобы было всё хорошо. Почему-то ни у кого не получается. Тут уже насмотрелись на бабашку вашу, это же ужоснах. Баш это компромисс с упором на склеивание команд, а не погромирование. Тем не менее, программировать на нем можно, хоть и не очень удобно. Может и хорошо, а то бы поттеринг и подобные на шелл-скриптах писали свою хренотень.

bread
()
Ответ на: комментарий от Nervous

ругают лисп за то, что в нём много скобачек

Не за много скобочек, а за глубокую их вложенность, что сильно грузит слабенький человеческий моск.

bread
()
Ответ на: комментарий от bread

Теперь попробуйте совместить, чтобы было всё хорошо. Почему-то ни у кого не получается.

У Xonsh, например, что-то получилось.

Баш это компромисс с упором на склеивание команд, а не погромирование. Тем не менее, программировать на нем можно, хоть и не очень удобно.

Вопросы к тому как можно погроммировать. С кучей подводных камней и самобытными идиомами, с минимумом профита по итогу. Хороший контр-пример – Fish, где весь мануал изучается за несколько часов без пердолинга с кавычками и подобной чепухой.

Может и хорошо, а то бы поттеринг и подобные на шелл-скриптах писали свою хренотень.

Он же за декларативщину топит.

anonymuse
()
Ответ на: комментарий от anonymuse

Хороший контр-пример – Fish, где весь мануал изучается за несколько часов

Но это никак не поможет понимать и использовать bash.

papin-aziat ★★★★★
()
Ответ на: комментарий от bread

Теперь попробуйте совместить, чтобы было всё хорошо

Не надо совмещать ужа с ежом. Пусть интерпретатор команд выполняет свою работу, а язык программирования свою.

Nervous ★★★★★
()
Ответ на: комментарий от papin-aziat

Хороший контр-пример – Fish, где весь мануал изучается за несколько часов

Но это никак не поможет понимать и использовать bash.

Сама по себе возможность не понимать и не использовать bash видится мне большим плюсом

alx777 ★★
()
Ответ на: комментарий от wandrien

В rc эта проблема решена.

There is no need for the distinction between $* and $@. There is no need for four types of quotation, nor the extremely complicated rules that govern them. In rc you use quotation marks when you want a syntax character to appear in an argument, or an argument that is the empty string, and at no other time. IFS is no longer used, except in the one case where it was indispensable: converting command output into argument lists during command substitution.

Какие ещё проблемы дизайна должны быть решены?

kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 4)
Ответ на: комментарий от wandrien

Возможно, мой голос относится к меньшинству, но разница в том, что стандартная библиотека — это решение, тогда как awk/sed — инструменты. Как мне, например, в Lua посчитать количество вхождений каждого слова в первой колонке? В awk это элементарно:

{dict[$1]++}
END {
  for (word in dict)
    print word, dict[word]
}
kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 2)
Ответ на: комментарий от Nervous

Почему отвратителен? Прост как кирпич, а значит предсказуем.

rtxtxtrx ★★★
()
Ответ на: комментарий от wandrien

для многих вещей, которые в bash делаются через сторонние костыли, нам вызов сторонних команд вообще не понадобиться. Вызываться будут команды «по существу».

Запрос списка файлов через ls — это сторонний костыль или команда «по существу»?

Сегодня это считается антипаттерном. Можно понять — люди видят ошибки и думают, что это проблема дизайна, которая должна быть решена на верхнем уровне.

Дело в том, что ложки «списка файлов» не существует. Можно заменить вывод файлов через ls на вывод строк через tar tf или cat $home/tasks и код продолжит работать, хотя последние две команды не возвращают список файлов. Хочешь узнать владельца файла? Вырежь колонку из подстроки, на месте которой случайно окажется ls -l.

Юникс переносит многие проблемы в область обработки текста, потому что текст универсален и неприхотлив — он повсюду в любой системе и любой программист уже давно умеет с ним работать. А не потому что они не могли предвидеть перенос строки в имени файла и сделать нечто негибкое и догматичное в стиле systemd, которое зато было бы надёжным.

kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 2)
Ответ на: комментарий от kaldeon

Какие ещё проблемы дизайна должны быть решены?

Навскидку:

  • не обрезать и не сжимать пробельные символы в конце строки;
  • не убирать пустые строки в массивах;
  • больше возможностей по работе с массивами;
  • рекурсивные структуры данных (в реальном мире людям нужно десериализовать JSON);
  • больше двух спец. символов подряд – нечитаемо;
  • разрешить пробелы вокруг присваивания;
  • динамическое связывание хуже статического.
anonymuse
()
Ответ на: комментарий от kaldeon

Запрос списка файлов через ls — это сторонний костыль или команда «по существу»?

Сегодня это считается антипаттерном.

Это считается антипаттерном, потому что перевод строки в имени файла – валидный символ.

anonymuse
()
Ответ на: комментарий от anonymuse

Ничего не имею против добрых намерений сторонников этого правила, но антипаттерном должны быть имена с переводом строки. Есть и другие антипаттерны (например, пробелы в начале и конце имени файла), которые делают невозможным вообще любую обработку текста (grep ‘\.txt$’ больше не работает).

kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 2)
Ответ на: комментарий от anonymuse

не обрезать и не сжимать пробельные символы в конце строки;

Согласен. Решено в рамках цитируемого мной отрывка. Эта проблема вызвана тем, что “$(cmd)”, который избегает IFS, нужно как-то обрезать, ведь cmd зачастую пишет перевод строки в конце. В rc это решено тем, что $(cmd) всегда безопасен (не сделает pathname expansion и, в целом, не будет себя вести как скрытый eval), что позволяет вместо отдельного “$(cmd)” с отдельными неожиданными правилами использовать только $(cmd) для всего и один общий механизм IFS, чтобы либо получить всё (включая перевод на новую строку), либо чистые строки без переводов.

не убирать пустые строки в массивах;

В массивах же допустимы пустые строки. Речь, наверное, идёт о встроенной функции read? Ужасная вещь. А главное проблема-то решается элементарно: созданием аналога /bin/cat, который читал бы только одну строку и возвращал eof, если её нет.

разрешить пробелы вокруг присваивания;

Решено в rc.

динамическое связывание хуже статического.

Но делает возможным простые решения, которые были бы нереализуемы в статическом связывании или требовали бы усложнения модели (в том числе для программиста).

kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 12)
Ответ на: комментарий от wandrien

Кстати, ты помнишь, как в bash обрезать значение переменной по символу, не вызывая внешних команд? И я не помню. Сраную перловку просто невозможно запомнить.

Я даже для сложения чисел использую внешнюю программу: var = `{echo $var + 1 | bc}.

В этом и сущность шелла: запуск команд. А потом из него действительно начали делать перл: переносить функции внешних инструментов, потому что чей-то кейс, возникающей в 1% случаях или работающий на 30 секунд дольше, не покрыт. Да и проекту GNU нужен вендор-лок.

kaldeon
()
Ответ на: комментарий от James_Holden

… оболочка видит, что это не валидный код lua, и заворачивает все как строку в вызов функции shell(). Если валидный код lua - кидается в repl.

Нельзя менять стейт непредсказуемо. Может получиться такая ерунда:

var = "hello $(rm $HOME)'

И это не вредоносный код, а просто пользователь опечатался и не понял, что попал в шелл, после чего ввёл ещё одну " и умер.

kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 1)
Ответ на: комментарий от papin-aziat

Привычка ставить кавычки везде.

Интересно, хорошая ли это привычка!?

Если смешивать стили, то однажды ошибёшься. Читающему код будет сложнее отличить стиль от ошибки, что, кажется, уже произошло в этом треде.

kaldeon
()
Ответ на: комментарий от kaldeon

В массивах же допустимы пустые строки. Речь, наверное, идёт о встроенной функции read? Ужасная вещь. А главное проблема-то решается элементарно: созданием аналога /bin/cat, который читал бы только одну строку и возвращал eof, если её нет.

Не, речь о том, что если для массива arr=(1 '' 3) не навернуть кавычек и других закорючек в правильной комбинации, то потеряется пустая строка. В rc, насколько понял, это тоже сводится к предыдущему пункту.

Получается, некоторые перечисленные родовые башепроблемы в ней решены.

Жаль как интерактивная не очень.

В rc нет локальных перченных?

anonymuse
()
Ответ на: комментарий от kaldeon

Я даже для сложения чисел использую внешнюю программу: var = `{echo $var + 1 | bc}.

С т.з. реализации добавить сложение чисел мало чего стоит. А вот пускать ради этого expr в цикле – выбор идеалиста, мягко говоря.

Как минимум расширять возможности самой оболочки имеет смысл на языке самой оболочки и все эти тормоза дадут о себе знать.

anonymuse
()
Ответ на: комментарий от anonymuse

Не, речь о том, что если для массива arr=(1 '' 3) не навернуть кавычек и других закорючек в правильной комбинации, то потеряется пустая строка.

Всё равно не понял. На моей машине этот код на баше создаёт массив из трёх строк. Что я делаю не так?

В rc нет локальных перченных?

Есть:

a = global
a = local echo $a
echo $a

# output:
# local
# global
fn read {
   var = $1 {
      $var = `{awk '{print;exit}'}
   }
}

Жаль как интерактивная не очень.

Для запуска предыдущей команды можно использовать команды " и "" (дока), для автодополнения имени файла — ctrl-f.

kaldeon
()
Последнее исправление: kaldeon (всего исправлений: 4)

Развитие в ИТ — это деградация! Когда же вы уже это поймёте?! Когда программа полностью выполняет все свои функции — это прекрасно! Но некоторым так и хочется развития дальше и вместо того, чтобы сказать себе «Стой! Остановись! Тут неуместно уже никакое развитие — программа полностью и хорошо выполняет свои функции». Продолжают пытаться в «развитие» наделяя программу неуместными функциями. Или кто-то им из ближнего окружения сказал бы: «Стой! Остановись! Ты серишь». Вот кто-то не сказал из ближнего окружения разработчику так и появился системмудэ и ты хочешь слепить из скриптового языка такое же уродство. Лови клоуна за это! Если бы Ленин был в ИТ, он бы уже сказал: «Юниксвей, юниксвей и ещё раз юниксвей!». В философии юниквея это сдерживание от лишнего сёра «развития» уже заложено! Космос — юниквеен, наша галактика — юниквейна, наша солнечная система — юниквейна, наша планета — юниксвейна, природа на планете — юниксвейна, человек — юниквеен, а оболочка системы должна быть почему-то не юниксвейной! Ничего гениальнее и лучше чем юниксвей в ИТ не было, нет, и не будет никогда! [/thread]

With ★☆☆
()
Ответ на: комментарий от With

Если вы видите юниксвей в природе, то не понимаете его или выдаёте за какое-то другое понятие.

kaldeon
()
Ответ на: комментарий от RedTerror

Прочитал. Этот язык концептуально сложный. Он вводит кучу собственных ad-hoc абстракций. И при этом не позволяет пользователю строить свои структуры данных как в полноценных ЯП.

wandrien ★★★
() автор топика
Ответ на: комментарий от anonymuse

рекурсивные структуры данных (в реальном мире людям нужно десериализовать JSON);

Подсчёт ссылок (и утечки памяти при циклических ссылках) или tracing GC (хотите, чтобы голый интерпретатор 10 Мб памяти жрал, как питон)?

динамическое связывание хуже статического.

А как это можно реализовать, если переменные в shell это переростки переменных окружения, которые как раз (в интерпретации, где переменная окружения = обычная переменная, процесс = функция) представляют из себя динамическое связывание?

shdown
()
Ответ на: комментарий от shdown

Подсчёт ссылок (и утечки памяти при циклических ссылках) или tracing GC (хотите, чтобы голый интерпретатор 10 Мб памяти жрал, как питон)?

Сколько памяти жрут Lua и QuickJS?

wandrien ★★★
() автор топика
Ответ на: комментарий от shdown

Подсчёт ссылок (и утечки памяти при циклических ссылках) или tracing GC (хотите, чтобы голый интерпретатор 10 Мб памяти жрал, как питон)?

Небольшой жор не страшен, не в embedded же это совать.

А как это можно реализовать, если переменные в shell это переростки переменных окружения, которые как раз (в интерпретации, где переменная окружения = обычная переменная, процесс = функция) представляют из себя динамическое связывание?

Как и много где: у глобального пространства имен динамическое связывание. Или в переменную env запихать.

anonymuse
()

Прикидываем, как будет выглядеть работа с пайпланами:

local sh = require("shellua") -- или как назовём

-- Простой пайплайн
sh.cmd("ls", "-la")
  :pipe("grep", "lua")
  :pipe("wc", "-l")
  :run()

-- С редиректами
sh.cmd("cat")
  :stdin("/etc/passwd")
  :pipe("sort")
  :stdout("sorted.txt")
  :run()

-- Fork с lua-функцией
sh.fork(function()
    for i = 1, 100 do
      print(i)
    end
  end)
  :pipe("grep", "[13579]$")
  :run()

-- Сжатие содержимого переменной без блокировки основного процесса
local handle = sh
  .printf("%s", bigtext)
  :pipe("gzip", "-9")
  :stdout("/tmp/tmp-1.gz")
  :spawn()
foo() -- выполняем еще какую-то работу параллельно
handle.wait()
wandrien ★★★
() автор топика
Последнее исправление: wandrien (всего исправлений: 1)
Ответ на: комментарий от wandrien

на чистом Си.

так это же негативная сторона, что не C++

safocl ★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.