Хочется отдохнуть...
Устал играть во всякие Eve, WoW, Dota etc.
Кто во что отдыхает играет, чтобы мозг отдохнул?
Устал играть во всякие Eve, WoW, Dota etc.
Кто во что отдыхает играет, чтобы мозг отдохнул?
Так как сегодня пятница и похвальной является любая шизофрения в рамках почти здравого смысла, представляю вашему вниманию часы!
clockrip
██████ ██████ ██████ ██████
██ ██ ██ ██ ██
██████ ██████ ██████ ██████
██ ██ ██ ██ ██
██████ ██████ ██████ ██████
clockrip -f O -s
OOOOOO OOOOOO OOOOOO OOOOOO OOOOOO OOOOOO
OO OO OO OO OO OO OO OO OO OO
OOOOOO OOOOOO OOOOOO OOOOOO OOOOOO OOOOOO
OO OO OO OO OO OO OO OO OO OO
OOOOOO OOOOOO OOOOOO OOOOOO OOOOOO OOOOOO
clockrip -f ▓ -s
▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓ ▓▓▓▓▓▓
▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓
▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓
▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓ ▓▓
▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓
Эта элегантная утилита позволит вам выводить время в виде больших букф чисел в разнообразном цвете и стиле, а элегантное название подчеркнёт туннельный синдром кистей ваших рук при наборе в эмуляторе терминала.
Теперь каждому найдётся своё место в этом мире и времени. Если вы клоун, то можете подчеркнуть свою самобытность выводя часы из клоунских улыбок, дарящих счастье людям во всём мире.
Суть, мне нужны были часы как tty-clock
нравится какой у них вывод, но только
мне нужно было иметь возможность просто выводить время в таком виде в файл, а не держать обновляющееся время в терминале с виду дурацкая идея, но так надо, в этом вся суть.
clockrip
Аргументы опциональные
-h
Отобразить справку-u
Выводить мировое UTC
время, а не локальное-s
Отображать секунды-f
Установить символ заполнитель (одно знакоместо)-ft [TEXT]
Установить символ заполнитель (одно знакоместо)-fw [TEXT]
Установить символ заполнитель (два знакоместа)-c [COLOR]
Установить цвет заливки-b [COLOR]
Установить цвет заливки фона-d
Включить эффект мигания для точек разделителей-t [TEMP]
Установить цвет через значение температуры в Цельсиях-bt [TEMP]
Установить цвет фона через значение температуры в Цельсиях-k [TEMP]
Установить цвет через значение температуры в Кельвинах-bk [TEMP]
Установить цвет фона через значение температуры в КельвинахКлючи -t -k -bt -bk
отменяют значение ключей -c -b
Ключи -t -k
переопределяют друг друга, какой задан последним тот и задаёт значение
Ключи -bt -bk
переопределяют друг друга, какой задан последним тот и задаёт значение
Цвет заливки может быть названием цвета из списка
black | red | green | yelow | blue | purple | cyan | gray
bblack | bred | bgreen | byelow | bblue | bpurple | bcyan | bgray
Цвет заливки может быть кодом цвета от 0
до 256
или от 000000
до FFFFFF
Если вместо времени отображается белиберда можно попробовать заменить -fw
на
-ft
и наоборот, утилита работает только с заливкой символами шириной 1 или 2
знакоместа от любого иного варианта отображаемое форматирование поедет.
Может кому надо тоже, эта супер пупер утилита на все времена UnixWay ультраортодоксальна и не умеет сама обновлять время, а тупо её выводит, поэтому
watch -tcn 60 clockrip -c green
Будет вызывать скрипт и обновлять время раз в минутуwatch -tcn 1 clockrip -s -c green
Будет вызывать скрипт и обновлять время раз в секундуwatch -tcn 1 clockrip -s -fw 😊
Будет вызывать скрипт и обновлять время раз в секундуНегодники
Lua
Си
Вишенка на торте, в этом описании текста больше чем кода в утилите
Привет, ЛОР!
Спустя 27 лет после версии 8.0 наконец вышла новая версия некогда популярного языка программирования Tcl и развиваемой вместе с ним библиотеки для создания пользовательских интерфейсов Tk.
Tcl является высокоуровневым скриптовым языком программирования с динамической типизацией. Отличительная особенность языка – все данные, включая код самой программы, могут быть представлены как строки, что создаёт обширные возможности для метапрограммирования и создания расширений.
В новом выпуске содержатся несовместимые изменения с версиями 8.x, поэтому было решено увеличить ведущий номер версии:
~
) в путях к файлам больше не указывает на домашнюю директорию пользователя;tcl_precision
больше не влияет на форматирование чисел.Также среди изменений:
В Tk 9.0 среди прочего были добавлены поддержка доступа к инструментам ОС, таким как трей, уведомления и печать документов, поддержка формата SVG, полный доступ к информации о графических файлах (метаданные и т.д.), поддержка жестов экрана и тачскрина.
>>> Подробности
Привет, ЛОР!
По-моему, было бы очень полезно иметь утилиту, работающую как grep
, но предназначенную для поиска чисел в пределах некоторого интервала от заданного значения. Например, если мы запускаем numgrep 1234 file.txt
, то утилита вычленяет в каждой строке файла всё, что можно прочитать как число, сравнивает каждое из чисел с 1234
, и если модуль разности не более 0.5
, то печатает всю найденную строку. Такими числами могли бы быть, например, 1234.1
, 1233.99
, 1.2344e3
. По умолчанию можно было бы в качестве доверительного интервала брать 0.5 от последней значащей цифры искомого числа, т.е. для 1234.5 было бы не +/-0.5
, а +/-0.05
, ну и, конечно, должна быть возможность задать интервал явно.
Вроде бы идея лежит на поверхности и не особо сложна в реализации (особенно если не сильно париться о скорости работы), но я не нашёл ничего готового на эту тему.
Есть tcp подключение к серверу. Сервер «выплевывает» сообщения по одному, tcpdump -ом видно что одно сообщение - один tcp сегмент. Между сообщениями 70мкс. Но linux + epoll «объединяют» по три или даже четыре прилетающих tcp сегмента в один и только после этого передается управление в программу для чтения буфера.
Что вызывает задержку для принятия решения 210мкс и более.
С какими флагами нужно создавать сокет и вызывать epoll, чтобы каждый tcp сегмент оказывался в программе?
В cвете последних событий принято решение настроить sing-box для работы как VPN.
Благо есть программа в каталоге f-droid (для меня это важно): https://f-droid.org/ru/packages/io.nekohasekai.sfa/
Есть короткая документация на английском тут: https://sing-box.sagernet.org/configuration/
Если кто-то уже настраивал и находил хорошую документацию по sing-box на русском языке прошу поделитесь. Нужна именно подробная документация, а не инструкция с готовым конфигом. Хочу понять что там за такая большая куча настроек и для чего они нужны, чтобы выполнить тонкую настройку.
Здравствуй, ЛОР! Искал сабж, не нашел чего-то актуального в 2024 году.
Имеется старый компьютер (2гб ОЗУ, HDD, Core2duo). Кде 5 и 6 нещадно виснут от каждого чиха, гном грузится в среднем по 7 минут, а под крысу фиг найдешь тему, от которой глаза не текут.
Что пробовал:
По дефолту нет анимаций, но есть picom
, где анимации вполне приличные.
Под XFWM KDE-шной темы по понятным причинам нет. Из-за этого шапка в половине приложений дефолтная, а в другой — Breeze.
Есть фанатский порт Breeze под XFWM, но он вырвиглазен.
XFCE+Kwin, тема – Breeze. Вроде как всё работает, только при входе экран жутко мигает. Пока что лучший вариант.
Cinnamon. Работает медленнее гнома.
Кастомные темы на крысу. Упирается в то, что тема GTK не сочетается с темой QT. Примеры: Arc (QT нет), Materia (QT нет), Adwaita (под gtk3 ужасна).
Что нужно:
С понятным интерфейсом. Fluxbox без меню «пуск» и bspwm без титлбара отпадают. Простая конфигурация и монолитность необязательны — из редактирования максимум панельку вверх подвинуть.
Темы, сочетающиеся с GTK и QT.
Буду благодарен.
UPD: я как раз всё осилю, мне чужой комп настроить надо
Помогите с идеями. Хочу чего-то, сам не могу пока понять чего.
Пролистав тонны скриншотов на лоре и r/unixporn понял что давно не собирал качественный рис, и решил вернутся к этой теме. i3 или awesomewm уже надоели. Да и тайлинг в целом надоел. Хочется чего нибудь необычного. Можно какой нибудь DE как-то необычно настроить. Не знаю. GnuStep (windowmaker) тоже хороший вариант, есть одна тема которую хочется попробовать. А так нет идей.
План такой: Arch, виртуалка, упаковка зеленого чая, закрыться от всех, и все выходные, как в старые добрые, под музыку что нибудь компилять.
inb4: Зачем? Да незачем, просто ради фана. Давно этим не занимался, пробила ностальгия по этим временам.
ps: пока писал, появилась идея сделать закос под MorphOS. Такой рис будет только у меня и у Майкла Джексона 😁
Устал байты дрочить и в свой быдлокод втыкать, надо отвлечься. Я в курсе что можно зайти на гитхаб или иное и найти там что угодно себе по душе, но долго объяснять, надоело рыть и править никому ненужное, хоца новенького, временного, отвлечься. Где есть лично вам бесячий баг или чего в чём-то не достаёт.
Всё, больше меня ничего не интересует. C
и/или Lua
Может утилита какая падает на C
, или очередная шизанутая игра на Lua
не запускается на новой версии Love2D
. Понятия не имею что можно предложить :)
То может помочь программка sk5filt в сочетании с ssh на localhost + sshd на VPS. Программка фильтрует трафик. Местно обслуживает что можно, остальное заворачивает на удалённое обслуживание. Т.е. не VPN, а прокси. В итоге работают и госуслуги, и всякие там техасы с нетфликсами и ютубами.
Скачать:
ftp://95.164.38.46/sk5filt.c.
Скомпилировать:
gcc -fno-builtin-log -Wall -Os -s -o sk5filt sk5filt.c
Инсталлировать:
su
mkdir /opt/sk5filt
cp sk5filt /opt/sk5filt
> /opt/sk5filt/hostlist
chmod 666 /opt/sk5filt/hostlist
^D
Запустить:
ssh -D 127.0.0.1:8081 <other-options> <vps>
/opt/sk5filt/sk5filt -a127.0.0.1:8080 -r/opt/sk5filt/hostlist 127.0.0.1:8081
Настроить браузер: открыть настройки прокси, в строке SOCKS указать IP 127.0.0.1, порт 8080, выбрать SOCKS5, установить использование DNS поверх SOCKS.
Дальше добавлять в /opt/sk5filt/hostlist то, что должно обслуживаться удалённо (куда вас не пускают просто так):
echo ti.com >> /opt/sk5filt/hostlist
echo analog.com >> /opt/sk5filt/hostlist
echo microchip.com >> /opt/sk5filt/hostlist
Туда же можно добавить youtube.com, ytimg.com, googlevideo.com и т.п., если злой админ не даёт вам смотреть ютубчик на работе, используя для этого DPI или ещё какую гадость. Если вы в РФ, не добавляйте rutracker.org и т.п. Потому что РКН запретил туда ходить.
Законно ли использовать программу? Вы не просто можете её использовать, вы должны её использовать. Потому что соблюдение антироссийских санкций противозаконно. Объясните своему злому админу на работе, что вам позарез нужен доступ к сайту техаса, потому что там куча полезной инфы на тему DSP. А проклятый буржуин вас не пускает. Разумеется, в нарушение российского законодательства. И вы, как законопослушный гражданин, просто обязаны нарушить антироссийские санкции.
Программу можно никуда не ставить и вообще пускать из-под юзера (если не вешать на порты до 1024). Ей всё равно, где она лежит и как её зовут. Можете положить её в ~/bin, а файл с записями для удалённого обслуживания в ~/sk5hosts (почему бы и нет?). Как порядочный UNIX-демон, программа попытается записать свой PID в /var/run/basename
.pid. Из-под юзера ей это не удастся, поэтому можно указать -p/tmp/sk5filt.pid или -p"".
У программы есть стандартная опция -h. А всякие подробности о её работе можно почитать в ней самой. Она по большей части состоит из комментариев, кода в ней кот наплакал. Комментарии на русском, в koi8-r. Если у вас какая-то другая кодировка, например utf8, то поможет iconv:
iconv -f koi8-r -t utf8 < sk5filt.c | less
Сколько будет лежать программа на этом временном ftp – никто не знает. Если у вас есть возможность положить её к себе и раздать всем желающим – you are welcome. Если хотите её доработать, то автор тоже всячески за. Сам он вряд ли станет, потому что некогда.
fooyin – это аудиопроигрыватель, созданный на Qt6 в стиле Foobar2000. На данный момент нативно доступен только на Linux. Плеер доступен по лицензии GNU GPL 3.
fooyin предлагает большое количество индивидуальных настроек для управления и воспроизведения музыкальной коллекции. Его можно расширить с помощью плагинов и языка FooScript. Воспроизведение звука поддерживается FFmpeg наряду с несколькими вариантами вывода, включая ALSA и PipeWire.
( читать дальше... )
>>> Подробности
micro – консольный текстовый редактор для Linux, написанный на языке Go и не имеющий зависимостей. Поддерживает плагины на языке Lua и различные команды во внутреннем терминале. В этом выпуске были добавлены новые настройки, улучшения синтаксической подсветки и поддержки мыши.
( читать дальше... )
>>> Подробности
Восьмилетняя дочь вице-президента американской компании Cloudflare Ричарда Робинетта (Richard Robinett), написала веб-приложение для чата. В предыдущем предложении преднамеренно пропущено слово «самостоятельно», хотя никто из взрослых или других детей ей не помогал. Девочка воспользовалась помощью двух программ-ассистентов - платформы для разработки ПО Workers AI и сервиса Cursor. Cursor представляет собой редактор кода со встроенным ассистентом на основе искусственного интеллекта, тогда как Workers AI отвечал за генерацию кусочков кода по запросу пользователя. Последовательно запрашивая нужные сниппеты кода, а потом применяя их к существующему проекту девочка смогла повторить обычный воркфлоу типичного веб-разработчика и получить нужный результат. Работа велась в онлайн-среде разработки от всё той же Cloudflare - Workers IDE, а вся необходимая инфраструктура была построена на облачной среде Cloudflare. Таким образом для работы требовался только браузер и настроенный аккаунт в Cloudflare - как разработка, так и развёртывание приложения целиком происходили на «облачных» ресурсах.
Видео с 10-ти минутным процессом работы можно посмотреть.
Кроме того, на проходящей выставке GamesCon стартап Exists представил альфа-версию своего проекта для разработки игр, позволяющей создавать не только отдельные ассеты, но и целиком 3D-сцены с частично прописанной игровой механикой. Этот проект ещё ждёт своего 8-ми летнего мальчика.
Перемещено hobbit из development
LOR славится своими специалистами по самым шизанутым вопросам. И вот у меня их есть.
Короче, современный веб - это звездец. Сайты жрут дохера ресурсов, бесконечные прокрутки, оптимизированный под мобилу размер текста итд.
У всего этого много разных причин, но одна из них - а потому что современные веб-технологии это позволяют.
Что же касается негативных эффектов у этой ситуации, то есть один, о котором задумываются редко. Чем сложнее веб - тем сложнее создать и поддерживать под него веб-браузер. Соответственно, рынок браузеров поделён между буквально несколькими крупными игроками: Хром Идж Фокс Сафари, а остальные браузеры в рамках статпогрешности. И это не есть хорошо.
Всякие там энтузиасты могли бы создать и нахайпить этакую инициативу, типа а давайте делать сайты как встарь. И смысл у этой инициативы был бы как раз не только в том, что блжат сайты не должны жрать как раньше космический шаттл, но и чтобы в интернете была сеть сайтов на скажем так важные темы (наука, искусство, рэперы, в общем темы могут быть любыми на самом деле), которые бы просто работали - одинаково и стабильно - в любом графическом броузере. В любом - то есть такой броузер может быть доморощенным, а ля нетсурф.
Короче идея такая чтобы сайты были на примитивных технологиях. Но не ради прикола или ностальгии, а так сказать с практическими целями: А) Чтобы работало на медленном коннекте (не везде в мире интернет быстрый, да и приколы со всякими замедлениями итп никто не отменял), Б) Чтобы не жрало ресурсы (опять же, не у всех в мире компы мощные, и ситуации в экономике тоже бывают разными: сегодня у тебя типа блокчейн крипта нейронки, а завтра ты в землянке с аналогом IBM PC XT из веток), В) Чтобы работало не только в крутых мейнстримовых брозуерах, но и в стареньких или доморощенных.
Я бы запилил, но у меня лапки. Может оно уже есть?
Спустя почти 3 года после предыдущей версии вышел движок OpenTESArena 0.15.0.
OpenTESArena – это OpenSource-реализация движка от The Elder Scrolls: Arena (первой игры серии The Elder Scrolls). OpenTESArena нативно доступен на Windows 10/11, Linux, Raspberry Pi, chromeOS и MacOS.
Нововведения:
Введён новый программный 3D-рендерер, который соответствует 256-цветной палитре оригинальной игры.
Улучшено обнаружение файлов данных TES:Arena (в Windows теперь проверяется директория C: Steam install по умолчанию).
Добавлена поддержка Mac на Apple Silicon.
Улучшено сохранение скриншотов.
Добавлена эксклюзивная опция полноэкранного режима.
Добавлена опция коррекции высоты пикселей.
В движение игрока внесены небольшие изменения в для соответствия оригинальной игре.
SDL обновлён до 2.0.10 для устранения периодической задержки, вызванной SDL_PollEvent().
Исправлен цвет тумана в Элден Гроув и Мерквуде.
Для трилогии The Elder Scrolls, помимо ОpenTESArena, развивается OpenSource-реализация движков от второй и третьей части, то есть Daggerfall Unity и OpenMW соответственно.
>>> Подробности
Фичи:
by-ts
, а его ник - классом ts-nick
odd
, а четные - классом even
Включает коды из других проектов:
Скриншоты
https://images.linuxforum.ru/images/2024/03/23/IZOBRAZENIE1471e033edbdb898.png https://images.linuxforum.ru/images/2024/03/23/IZOBRAZENIE.png
Установка
Ctrl+A
и вставьте код скрипта, затем нажмите Ctrl+S
.Более простой способ установки
Установка на телефон
Настройка
В настройках сайта «Форматирование по умолчанию» должно быть LORCODE
.
Чтобы выключить опцию, поставьте false
в строчке с соответствующей опцией. Чтобы включить опцию, поставьте true
.
NEW_TO_OLD_SEARCH_BY_DEFAULT HIDE_NEWS_AND_GALLERY ADD_TAGS_AND_DOCS TECH_ONLY_BY_DEFAULT HIDE_TAG_CLOUD HIDE_STARS HIDE_REACTIONS
Создание юзерстилей
/*Чередующиеся сообщения разных цветов*/
.messages .odd {
background-color: #FBFCFB;
}
.messages .even {
background-color: #F0FFF7;
}
/*Кастомизируем вид кнопок редактора сообщений*/
#btn-i {
font-style: italic;
}
#btn-quote::before {
content: 'Цитата';
}
#btn-quote span {
display: none;
}
// ==UserScript==
// @name LORScriptPack
// @description Пак скриптов для ЛОРа
// @namespace linux.org.ru
// @include http://www.linux.org.ru/*
// @include https://www.linux.org.ru/*
// @author damix9
// @license MIT
// @version 2.1
// ==/UserScript==
/*
MIT License
Copyright (c) 2024 damix9
Copyright (c) 2022 OpenA
Copyright (c) 2007-2009 Steven Levithan <stevenlevithan.com>
Copyright (с) 2013 Oleksandr Natalenko aka post-factum
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Настройки
const NEW_TO_OLD_SEARCH_BY_DEFAULT = false;
const HIDE_NEWS_AND_GALLERY = false;
const ADD_TAGS_AND_DOCS = true;
const TECH_ONLY_BY_DEFAULT = false;
const HIDE_TAG_CLOUD = false;
const HIDE_STARS = false;
const HIDE_REACTIONS = false;
// Глобальные константы и переменные
const parser = new DOMParser();
const formats = ['jpeg', 'jpg', 'png', 'webp', 'tif', 'tiff'];
let CommentForm = null;
let tagListWrapper = null;
let divPopup = null; let timer = null;
// Функции
function _setup(el, attrs, events) {
if (!el)
return '';
switch (typeof el) {
case 'string':
el = document.createElement(el);
case 'object':
for (const key in attrs) {
attrs[key] === undefined ? el.removeAttribute(key) :
key === 'html' ? el.innerHTML = attrs[key] :
key === 'text' ? el.textContent = attrs[key] :
key in el && (el[key] = attrs[key] ) == attrs[key]
&& el[key] == attrs[key] || el.setAttribute(key, attrs[key]);
}
for (const name in events) {
if (!events[name])
continue;
if (Array.isArray(events[name]))
events[name].forEach(handler => el.addEventListener(name, handler, false));
else
el.addEventListener(name, events[name], false);
}
}
return el;
}
// Возвращает расширение файла, находящегося по адресу url
function _getUrlExt(url) {
let oURL = new URL(url);
let path = oURL.pathname;
return path.split('.').pop().toLowerCase();
}
// Возвращает название темы, выбранной в настройках
function getCurrentTheme() {
let firstLinkNode = document.head.querySelector('link');
let cssUrl = new URL(firstLinkNode.href);
return cssUrl.pathname.split('/')[1]
}
// Добавляет CSS к странице
function addCss(sheet) {
var head = document.head;
let style = _setup('style', { text: sheet });
head.appendChild(style);
}
function strContains(str, phrase) {
return str.indexOf(phrase) !== -1;
}
// В течение 3 секунд показывает всплывающее уведомление с текстом text
function popup(text) {
clearTimeout(timer);
divPopup.innerHTML = text;
divPopup.style.visibility = 'visible';
divPopup.classList.add('shown');
timer = setTimeout(() => {
divPopup.classList.remove('shown');
timer = setTimeout(() => {
divPopup.style.visibility = 'hidden';
}, 1000)
}, 3000)
}
//******************************************************************************************
//
// A CGI program uses the following syntax to add cookie information to the HTTP header:
//
// Set-Cookie: name=value
// [;EXPIRES=dateValue]
// [;DOMAIN=domainName]
// [;PATH=pathName]
// [;SECURE]
//
// This function sets a client-side cookie as above. Only first 2 parameters are required
// Rest of the parameters are optional. If no szExpires value is set, cookie is a session cookie.
//
// Prototype : setCookie(szName, szValue [,szExpires] [,szPath] [,szDomain] [,bSecure])
//******************************************************************************************
function setCookie(szName, szValue, szExpires, szPath, szDomain, bSecure)
{
var szCookieText = escape(szName) + '=' + escape(szValue);
szCookieText += (szExpires ? '; EXPIRES=' + szExpires.toGMTString() : '');
szCookieText += (szPath ? '; PATH=' + szPath : '');
szCookieText += (szDomain ? '; DOMAIN=' + szDomain : '');
szCookieText += (bSecure ? '; SECURE' : '');
document.cookie = szCookieText;
}
//******************************************************************************************
// This functions reads & returns the cookie value of the specified cookie (by cookie name)
//
// Prototype : getCookie(szName)
//******************************************************************************************
function getCookie(szName)
{
var szValue = null;
if(document.cookie) //only if exists
{
var arr = document.cookie.split((escape(szName) + '='));
if(2 <= arr.length)
{
var arr2 = arr[1].split(';');
szValue = unescape(arr2[0]);
}
}
return szValue;
}
//******************************************************************************************
// To delete a cookie, pass name of the cookie to be deleted
//
// Prototype : deleteCookie(szName)
//******************************************************************************************
function deleteCookie(szName)
{
var tmp = getCookie(szName);
if(tmp)
{ setCookie(szName,tmp,(new Date(1))); }
}
// Добавляет к форме отправке сообщения кнопки для редактирования разметки, делает поле ввода сообщения широким
function handleCommentForm(form) {
const TEXT_AREA = form.elements.msg, TITLE_AREA = form.elements.title || { value: '' };
const MARKUP_PANEL = _setup('div', { id: 'markup-panel', class: 'lorcode'});
for (let attrs of [
{ lorcode: 'b' , title: 'Жирный' },
{ lorcode: 'i' , title: 'Курсив' },
{ lorcode: 'u' , title: 'Подчеркнутый' },
{ lorcode: 's' , title: 'Зачеркнутый' },
{ lorcode: 'em' , title: 'Курсив выделения' },
{ lorcode: 'strong' , title: 'Жирный выделения' },
{ lorcode: 'url' , title: 'Ссылка' },
{ lorcode: 'list' , title: 'Список' },
{ lorcode: 'list' , title: 'Нумерованный список', attr: '1' },
{ lorcode: '*' , title: 'Элемент списка' },
{ lorcode: 'pre' , title: 'Преформатированный текст' },
{ lorcode: 'br' , title: 'С новой строки' },
{ lorcode: 'code' , title: 'Код' },
{ lorcode: 'code' , title: 'Bash', attr: 'bash' },
{ lorcode: 'code' , title: 'HTML', attr: 'html' },
{ lorcode: 'code' , title: 'CSS', attr: 'css' },
{ lorcode: 'code' , title: 'JavaScript', attr: 'js' },
{ lorcode: 'code' , title: 'PHP', attr: 'php' },
{ lorcode: 'code' , title: 'SQL', attr: 'sql' },
{ lorcode: 'code' , title: 'Си', attr: 'c' },
{ lorcode: 'code' , title: 'C++', attr: 'cpp' },
{ lorcode: 'code' , title: 'Java', attr: 'java' },
{ lorcode: 'inline', title: 'Код в той же строке' },
{ lorcode: 'user' , title: 'Ник пользователя' },
{ lorcode: 'quote' , title: 'Цитата' }
]) {
attrs.type = 'button';
attrs.id = 'btn-' + attrs.lorcode.toLowerCase();
attrs.class = 'btn btn-default';
let label = _setup('span', { text: attrs.lorcode });
if (attrs.attr) {
let a = attrs.attr.toLowerCase();
attrs.id += `-${a}`;
label.innerHTML += `=${a}`
}
let button = _setup('button', attrs);
button.appendChild(label);
MARKUP_PANEL.append(button)
}
lorcodeMarkup = lorcodeMarkup.bind(TEXT_AREA);
for (let i = 0; i < MARKUP_PANEL.childNodes.length; i++) {
let btn = MARKUP_PANEL.childNodes[i];
btn.addEventListener('click', function(e) {
e.preventDefault();
const tag = this.getAttribute('lorcode');
const attr = this.getAttribute('attr');
lorcodeMarkup(tag, attr)
});
}
TEXT_AREA.parentNode.firstElementChild.after(MARKUP_PANEL);
TEXT_AREA.style = "width: 70em; height: 10em;"
}
// Пишет в поле ввода сообщения текст str, туда, где стоял курсор,
// Ставит курсор в конец добавленного текста и выделяет поле ввода
function injectText(str) {
const txtArea = CommentForm.elements.msg;
let val = txtArea.value,
len = txtArea.value.length,
start = txtArea.selectionStart,
end = txtArea.selectionEnd;
txtArea.value = val.substring(0, start) + str + val.substring(end);
txtArea.selectionStart = txtArea.selectionEnd = start + str.length;
txtArea.focus()
}
// Берет выделенный текст в указанный тег с указанным аттрибутом
// Если тег br или * то ставит их еще и в начале каждой строки выделенного текста
// Всегда вызывать bind() или call(), передав в них textarea, в которой надо делать разметку
function lorcodeMarkup(tag, attr) {
const val = this.value,
end = this.selectionEnd,
start = this.selectionStart,
collp = start === end;
let mtext = '', open = '', close = '',
soff = 0, eoff = 0;
mtext = val.substring(start, end);
switch (tag) {
case 'br':
if (!collp)
mtext = mtext.replace(/\n/gm, '\n'+'[br]');
else
open = '[br]';
break;
case '*':
open = '[*]';
if (!collp)
mtext = mtext.replace(/\[\/?\*\]/g, '').replace(/\n/gm, '\n'+'[*]');
break;
case 'url':
let uri = prompt('Введите адрес ссылки');
if (uri) {
open = `[url=${uri}]`;
close = '[/url]';
}
else {
return;
}
break;
default:
open = attr ? `[${tag}=${attr}]` : `[${tag}]`;
close = `[/${tag}]`;
}
soff = open.length; eoff = open.length + mtext.length;
this.value = val.substring(0, start) + open + mtext + close + val.substring(end);
this.focus();
this.setSelectionRange(start + soff, start + eoff);
this.dispatchEvent(new InputEvent('input', { bubbles: true }))
}
// Отправлет сообщение с текстом msg в тему c id topic
function sendMessageToTopic(topic, msg) {
let newTab = open(`https://www.linux.org.ru/add_comment.jsp?topic=${topic}&msg=${msg}`, '_blank');
newTab.focus()
}
// Обратиться к пользователю по нику
function castUser(nick) {
injectText('[user]' + nick + '[/user], ')
}
// Цитировать. Аргументы опциональны. Если указаны, то цитировать с ником.
function quote(nick, link) {
const wSelect = window.getSelection();
if (wSelect.isCollapsed) {
return
}
let simple = (nick === undefined) && (link === undefined);
let text = simple ? '' : '\n[user]' + nick + '[/user] [url=' + link + ']пишет[/url]:\n';
text += '[quote]' + wSelect.toString().trim() + '[/quote]' + '\n';
injectText(text)
}
// Отправить модераторам ссылку на сообщение с нарушением правил
function reportHam(link) {
let violation = prompt('Введите текст жалобы');
if (violation == null) {
return
}
let specTopicId = getCookie('SPECTOPIC_ID');
let text = link;
if (violation != "") {
text += '%0D%0A%5Bbr%5D' + violation; // перенос строки и [br]
}
if (!(specTopicId)) {
alert('Не задан спецтопик!\nОткройте его (Форум -> Linux-org-ru -> Ссылки на некорректные сообщения) и нажмите кнопку \"Это спецтопик\".');
return
}
sendMessageToTopic(specTopicId, text)
}
// Сохраняет ID текущей темы в cookie SPECTOPIC_ID
function itsSpecTopic() {
let path = window.location.pathname;
let topicId = path.split('/')[3];
let expires = new Date();
expires.setDate(expires.getDate() + 60);
setCookie('SPECTOPIC_ID', topicId, expires, '/');
alert('Спецтопик установлен')
}
let firstLetter = '';
// Обновляет отображаемый список тегов, показывает теги, соответстующие
// поисковому запросу, т.е. начинающиеся на строку, содержащуюся в поле ввода
async function searchTags(e) {
let query = e.target.value.trim().toLowerCase();
let queryFirstLetter = query.charAt(0);
if (queryFirstLetter != firstLetter) {
firstLetter = queryFirstLetter;
if (firstLetter != '') {
let response = await fetch('https://www.linux.org.ru/tags/' + firstLetter);
let txt = await response.text();
let oDoc = parser.parseFromString(txt, 'text/html');
let content = oDoc.getElementById('bd');
let tagList = content.getElementsByTagName('ul')[0];
let oldTagList = tagListWrapper.firstChild;
if (oldTagList) {
tagListWrapper.replaceChild(tagList, oldTagList)
}
else {
tagListWrapper.appendChild(tagList);
}
}
}
let tagList = tagListWrapper.firstChild;
if (tagList) {
for (let i = 0, c = tagList.children.length; i < c; i++) {
let tag = tagList.children[i];
let s = tag.children[0].text;
if (s.startsWith(query)) {
tag.style.display = 'list-item'
}
else {
tag.style.display = 'none'
}
}
}
}
// Добавляет к сообщению (теме или комментарию) недостающие ссылки внизу.
// Передать DOM Node элемента div.reply сообщения и логин его отправителя.
function addReplyLinks(replyNode, author) {
let links = replyNode.firstElementChild;
let linkToComment = links.lastElementChild.firstElementChild.href;
let nick = _setup(
'a',
{ text: 'Ник', href: linkToComment + '#nick' },
{ click: (e) => { e.preventDefault(); castUser(author) } }
);
let report = _setup(
'a',
{ text: 'Пожаловаться', href: linkToComment + '#report' },
{ click: (e) => { e.preventDefault(); reportHam(linkToComment) } }
);
let simpleQuote = _setup(
'a',
{ text: 'Цитировать', href: linkToComment + '#quote' },
{ click: (e) => { e.preventDefault(); quote() } }
);
let advancedQuote = _setup(
'a',
{ text: 'Цитировать с ником', href: linkToComment + '#quote' },
{ click: (e) => { e.preventDefault(); quote(author, linkToComment) } }
);
let nickLi = _setup('li'); nickLi.appendChild(nick);
let reportLi = _setup('li'); reportLi.appendChild(report);
let quoteLi = _setup('li'); quoteLi.appendChild(simpleQuote);
let advancedQuoteLi = _setup('li'); advancedQuoteLi.appendChild(advancedQuote);
links.firstElementChild.before(nickLi);
nickLi.after(' ');
links.appendChild(reportLi);
reportLi.before(' ');
links.appendChild(quoteLi);
quoteLi.before(' ');
links.appendChild(advancedQuoteLi);
advancedQuoteLi.before(' ')
}
// Принимает событие клика, копирует в буфер обмена текст поля, на котором кликнули
function copyNick (e) {
e.target.select();
if (document.execCommand('copy')) {
popup('Текст скопирован в буфер обмена')
}
}
// Принимает блок с кодом, выделяет его текст
function selectCode (codeNode) {
let range = document.createRange();
range.selectNodeContents(codeNode.firstElementChild);
let selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range)
}
// Принимает блок с кодом, сворачивает/разворачивает его
function toggleCodeSpoiler(codeNode) {
codeNode.classList.toggle('unspoiled')
}
/*
* Date Format 1.2.3
* (c) 2007-2009 Steven Levithan <stevenlevithan.com>
* MIT license
*
* Includes enhancements by Scott Trenda <scott.trenda.net>
* and Kris Kowal <cixar.com/~kris.kowal/>
*
* Accepts a date, a mask, or a date and a mask.
* Returns a formatted version of the given date.
* The date defaults to the current date/time.
* The mask defaults to dateFormat.masks.default.
*/
var dateFormat = function () {
var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
timezoneClip = /[^-+\dA-Z]/g,
pad = function (val, len) {
val = String(val);
len = len || 2;
while (val.length < len) val = "0" + val;
return val;
};
// Regexes and supporting functions are cached through closure
return function (date, mask, utc) {
var dF = dateFormat;
// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !/\d/.test(date)) {
mask = date;
date = undefined;
}
// Passing date through Date applies Date.parse, if necessary
date = date ? new Date(date) : new Date;
if (isNaN(date)) throw SyntaxError("invalid date");
mask = String(dF.masks[mask] || mask || dF.masks["default"]);
// Allow setting the utc argument via the mask
if (mask.slice(0, 4) == "UTC:") {
mask = mask.slice(4);
utc = true;
}
var _ = utc ? "getUTC" : "get",
d = date[_ + "Date"](),
D = date[_ + "Day"](),
m = date[_ + "Month"](),
y = date[_ + "FullYear"](),
H = date[_ + "Hours"](),
M = date[_ + "Minutes"](),
s = date[_ + "Seconds"](),
L = date[_ + "Milliseconds"](),
o = utc ? 0 : date.getTimezoneOffset(),
flags = {
d: d,
dd: pad(d),
ddd: dF.i18n.dayNames[D],
dddd: dF.i18n.dayNames[D + 7],
m: m + 1,
mm: pad(m + 1),
mmm: dF.i18n.monthNames[m],
mmmm: dF.i18n.monthNames[m + 12],
yy: String(y).slice(2),
yyyy: y,
h: H % 12 || 12,
hh: pad(H % 12 || 12),
H: H,
HH: pad(H),
M: M,
MM: pad(M),
s: s,
ss: pad(s),
l: pad(L, 3),
L: pad(L > 99 ? Math.round(L / 10) : L),
t: H < 12 ? "a" : "p",
tt: H < 12 ? "am" : "pm",
T: H < 12 ? "A" : "P",
TT: H < 12 ? "AM" : "PM",
Z: utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
o: (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
S: ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
};
return mask.replace(token, function ($0) {
return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
});
};
}();
// Some common format strings
dateFormat.masks = {
"default": "ddd mmm dd yyyy HH:MM:ss",
shortDate: "m/d/yy",
mediumDate: "mmm d, yyyy",
longDate: "mmmm d, yyyy",
fullDate: "dddd, mmmm d, yyyy",
shortTime: "h:MM TT",
mediumTime: "h:MM:ss TT",
longTime: "h:MM:ss TT Z",
isoDate: "yyyy-mm-dd",
isoTime: "HH:MM:ss",
isoDateTime: "yyyy-mm-dd'T'HH:MM:ss",
isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};
// Internationalization strings
dateFormat.i18n = {
dayNames: [
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
],
monthNames: [
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
]
};
// Принимает событие отправки формы поиска в Google.
// Перенаправляет пользователя на страницу поиска Google по сайту
function searchByGoogle(event) {
event.preventDefault();
let term = document.getElementById('qg').value;
let redirect = 'https://www.google.com/search?q=' + term + ' site:linux.org.ru';
window.location.href = redirect
}
// Основной код
let LOR_CSS = `
.code {
overflow: scroll;
}
.code.spoiled {
overflow-y: scroll;
}
.code pre {
overflow-x: unset;
overflow-y: unset;
word-wrap: initial;
}
pre code {
white-space: pre;
}
.code .spoiler-open {
display: none;
}
#markup-panel .btn {
margin: 2px;
}
#qg {
margin-right: 5px;
}
a img.lorpic {
max-width: 700px;
}
@media (max-width: 900px) {
a img.lorpic {
max-width: 60vw;
height: auto;
}
.popup-message {
width: 90vw;
}
}
.user-tag {
display: none;
}
.popup-message {
visibility: hidden;
opacity: 0;
position: fixed;
right: 20px;
bottom: 20px;
padding: 10px;
width: 300px;
border-style: solid;
transition-property: opacity;
transition-duration: 1s;
transition-timing-function: linear;
}
.shown {
visibility: visible;
opacity: 1;
}
`;
const LOR_DARK = `
.messages .by-ts {
background-color: #3d2300;
}
a img.lorpic {
background-color: #FFC;
}
.popup-message {
border-width: thin;
border-color: #8ae234;
background-color: #033;
}
`;
const LOR_LIGHT = `
.messages .by-ts {
background-color: #FFC;
}
.popup-message {
border-width: medium;
border-color: #000;
background-color: #FC6;
}
div.code {
background-color: #FFF;
}
`;
const LOR_BLACK = `
.ts-nick::after {
content: '[ТС]';
color: #F30;
font-weight: bold;
}
a img.lorpic {
background-color: #FFC;
}
.popup-message {
border-width: thin;
border-color: #8ae234;
background-color: #033;
}
`;
if (HIDE_TAG_CLOUD) {
LOR_CSS += `
.tag-cloud {
display: none;
}
`
}
if (HIDE_STARS) {
LOR_CSS += `
.stars {
display: none;
}
`
}
if (HIDE_REACTIONS) {
LOR_CSS += `
.reactions {
display: none;
}
`
}
const theme = getCurrentTheme();
addCss(LOR_CSS);
if (theme == 'tango') {
addCss(LOR_DARK)
}
else if (theme == 'waltz') {
addCss(LOR_LIGHT)
}
else if (theme == 'black') {
addCss(LOR_BLACK)
}
CommentForm = document.forms.commentForm || document.forms.messageForm;
if (CommentForm) {
handleCommentForm(CommentForm);
}
let firstSign = document.querySelector('footer div.sign');
let TS = firstSign ? firstSign.firstElementChild.textContent : null;
if (TS) {
let nextBlock = firstSign.parentElement.nextElementSibling;
if (nextBlock.className == "reply") {
addReplyLinks(nextBlock, TS)
}
}
let comments = document.getElementById('comments') && document.getElementById('comments').getElementsByClassName('msg-container');
if (comments) {
for (let i = 0, c = comments.length; i < c; i++) {
let sign = comments[i].getElementsByClassName('sign')[0];
let reply = comments[i].getElementsByClassName('reply')[0];
let author = sign.firstElementChild.textContent;
let parentNode = comments[i].parentElement;
if (author == TS) {
parentNode.classList.add('by-ts');
sign.classList.add('ts-nick')
}
// Если индекс комментария в массиве comments четный,
if ((i % 2) == 0) {
// то по счету комментарий нечетный
parentNode.classList.add('odd')
}
else {
parentNode.classList.add('even')
}
// Первый комментарий имеет индекс 0
if (reply) {
addReplyLinks(reply, author)
}
}
}
// Делаем местное время
let times = document.getElementsByTagName("time");
let c = times.length;
for (i = 0; i < c; i++) {
let attrTime = new Date(times[i].getAttribute("datetime", 0));
let nowTime = new Date();
let diff = Math.round(nowTime.getTime() / 1000) - Math.round(attrTime.getTime() / 1000);
let attrDay = new Date(attrTime.getTime());
let nowDay = new Date(nowTime.getTime());
attrDay.setHours(0, 0, 0, 0);
nowDay.setHours(0, 0, 0, 0);
let today = attrDay.getTime() == nowDay.getTime();
let yesterday = (attrDay.getTime() + 86400000) == nowDay.getTime();
let timeText;
if ((strContains(document.URL, "/tracker") || strContains(document.URL, "/notifications"))) {
let minutes = Math.ceil(diff / 60);
if (minutes < 60) {
timeText = minutes + " мин."
}
else if (today) {
timeText = dateFormat(attrTime.getTime(), "HH:MM:ss")
}
else if (yesterday) {
timeText = "вчера " + dateFormat(attrTime.getTime(), "HH:MM:ss")
}
else {
timeText = dateFormat(attrTime.getTime(), "dd.mm.yy HH:MM")
}
}
else {
if (today) {
timeText = "сегодня " + dateFormat(attrTime.getTime(), "HH:MM")
}
else if (yesterday) {
timeText = "вчера " + dateFormat(attrTime.getTime(), "HH:MM")
}
else {
timeText = dateFormat(attrTime.getTime(), "dd.mm.yyyy HH:MM")
}
}
times[i].innerHTML = timeText
}
// Настраиваем меню
if (theme == 'tango' || theme == 'waltz') {
let menu = document.getElementsByClassName('menu')[0].getElementsByTagName('ul')[0]; // Главное меню
if (TECH_ONLY_BY_DEFAULT) {
menu.children[4].firstElementChild.href = '/tracker/?filter=tech';
}
if (HIDE_NEWS_AND_GALLERY) {
// Убираем первые два раздела - новости и галерею
menu.firstElementChild.remove();
menu.firstElementChild.remove();
}
if (ADD_TAGS_AND_DOCS) {
let itmTags = _setup('li'); let itmWiki = _setup('li');
let linkTags = _setup(
'a',
{ href: '/tags/', text: 'Теги' }
);
let linkWiki = _setup(
'a',
{ href: 'http://lorwiki.zhbert.ru/', text: 'Документация', target: '_blank' }
);
itmTags.appendChild(linkTags); itmWiki.appendChild(linkWiki);
menu.appendChild(itmTags);
menu.appendChild(itmWiki);
itmWiki.before(' ');
}
}
// =================================================================================
let related = document.getElementById('related-topics');
if (related) {
let btnItsSpectopic = _setup(
'input',
{ type: 'button', value: 'Это спецтопик' },
{ click: itsSpecTopic }
);
related.before(btnItsSpectopic);
}
// Добавляем всплывающее уведомление
divPopup = _setup(
'div',
{ class: 'popup-message' }
);
document.body.appendChild(divPopup);
// Сворачиваемый и копируемый код
let codes = document.querySelectorAll('div.code');
for (let i = 0, c = codes.length; i < c; i++) {
let code = codes[i];
let linkToggleCodeSpoiler = _setup(
'a',
{ href: '#toggleCodeSpoiler', text: 'Развернуть/Свернуть' },
{ click: (e) => { e.preventDefault(); toggleCodeSpoiler(code) } }
);
let linkSelectCode = _setup(
'a',
{ href: '#selectCode', text: 'Выделить' },
{ click: (e) => { e.preventDefault(); selectCode(code) } }
);
let codeControls = _setup(
'div',
{ class: 'code-controls' }
);
codeControls.appendChild(linkToggleCodeSpoiler);
codeControls.appendChild(linkSelectCode);
linkToggleCodeSpoiler.before('[');
linkSelectCode.before('] [');
linkSelectCode.after(']');
code.before(codeControls)
}
// Картинки
let links = document.getElementsByTagName('a');
for (i = 0, c = links.length; i < c; i++) {
let link = links[i];
if (!link.getAttribute('itemprop')) {
let url = link.href;
let ext = _getUrlExt(url);
if (formats.includes(ext)) {
let content = link.textContent;
if (content != 'Просмотр') {
let image = _setup(
'img',
{ class: 'lorpic', src: url, title: content, alt: url },
);
link.innerHTML = '';
link.target = '_blank';
link.appendChild(image)
}
}
}
}
// ================================================================================
if (window.location.pathname == '/tags/') {
tagSearchBar = _setup('div', { style: 'margin: 20px 0' });
let tagSearchInput = _setup(
'input',
{ placeholder: 'Поиск меток ...', size: 30, autofocus: true },
{ keyup: searchTags }
);
tagSearchBar.appendChild(tagSearchInput);
let tagsFirstLetters = document.getElementsByClassName('tags-first-letters')[0];
tagsFirstLetters.after(tagSearchBar);
tagListWrapper = _setup('span');
tagSearchBar.after(tagListWrapper);
document.getElementsByTagName('section')[0].className = 'tag-cloud'
}
if (window.location.pathname.startsWith('/people')) {
let profile = document.getElementsByClassName('vcard')[0]
if (profile) {
let nick = profile.getElementsByClassName('nickname')[0];
let nickName = '[user]' + nick.textContent.trim() + '[/user]';
profile.appendChild(_setup('br'));
profile.appendChild(_setup('b', { text: 'Копировать ник: ' }));
let copyInput = _setup(
'input',
{ value: nickName, size: nickName.length, readOnly: true },
{ click: copyNick }
);
profile.appendChild(copyInput);
profile.appendChild(_setup('br'))
}
}
if ((window.location.pathname == '/search.jsp') && (window.location.search == '')) {
let searchContainer = document.getElementById('bd');
let hdrGoogle = _setup(
'h1',
{ text: 'Поиск в Google' }
);
let inpGoogle = _setup(
'input',
{ id: 'qg', size: 50, class: 'input-lg', type: 'search', maxlength: 250 }
);
let btnGoogle = _setup(
'button',
{ class: 'btn btn-primary', text: 'Поиск' }
)
let googleSearchBar = _setup(
'form',
{ class: 'control-group' },
{ submit: searchByGoogle }
);
googleSearchBar.appendChild(hdrGoogle);
googleSearchBar.appendChild(inpGoogle);
googleSearchBar.appendChild(btnGoogle);
searchContainer.appendChild(googleSearchBar);
let defaultSortOrder = _setup(
'input',
{ type: 'hidden', name: 'sort', value: 'DATE' }
);
if (NEW_TO_OLD_SEARCH_BY_DEFAULT) {
searchContainer.getElementsByTagName('form')[0].appendChild(defaultSortOrder)
}
}
Сижу в наушниках за компьютером. Музыку тихо слушаю, но иногда это надоедает. Хочется чего-то нейтрального, чтобы заглушало шум извне, но не акцентировало на себе внимание. Есть какие-то сборники таких звуков? Чтобы понакачать торрентов и выбрать то, что подходит
Я уверен - многие из нас что-то ставят для фона. И сидят в «ушках» когда работают.
Интересно - что у кого играет, и отвлекает или нет?
Ну, понеслась…
ПыСы. Модель «ушей» - тоже интересует. Сейчас точно тряпками закидают…
Я не буду расписывать преимущества ZSH над Bash, отмечу лишь то, что ZSH используется по дефолту во многих дистрибутивах Linux, а также с недавних пор и в macOS (тут должна быть шутка про Торвальдса и его макбук). Главной причиной повсеместной замены bash на zsh является встроенный механизм модулей, поверх которого было навалено такое великолепие, как Oh My Zsh.
( читать дальше... )
JB требует VPN.
VS требует Windows.
VSCode сливает всё на сервер дополнениями.
Что выбрать, чтобы надолго и минимум зависимости проекта от компаний?
Vim с плагинами - инородная хрень. Голый Vim для front/back -> (‿|‿)
← предыдущие | следующие → |