Текстовый редактор — это вам не высшая математика, тут думать надо

    Современные текстовые редакторы умеют не только бибикать и не давать выйти из программы. Оказывается, внутри них кипит очень сложный метаболизм. Хотите узнать, какие ухищрения предпринимаются для быстрого пересчета координат, как к тексту приделываются стили, фолдинги и софтврапы и как это всё обновляется, при чем тут функциональные структуры данных и очереди с приоритетами, а также как обманывать пользователя — добро пожаловать под кат!



    В основе статьи — доклад Алексея Кудрявцева с Joker 2017. Алексей уже лет 10 пишет Intellij IDEA в JetBrains. Под катом вы найдете видео и текстовую расшифровку доклада.



    Структуры данных внутри текстовых редакторов


    Чтобы понять, как устроен редактор, давайте его напишем.



    Всё, наш простейший редактор готов.

    Внутри редактора текст легче всего хранить в массиве символов, ну или, что то же самое (в смысле организации памяти), в Java-классе StringBuffer. Чтобы получить какой-нибудь символ по смещению, мы вызываем метод StringBuffer.charAt(i). А чтобы вставить в него символ, который мы напечатали на клавиатуре, вызовем метод StringBuffer.insert(), который вставит символ куда-то в середину.

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

    К сожалению, с этим редактором возникает проблема масштаба. Представим, что мы напечатали в нём очень много текста и собираемся вставить в середину еще одну букву. Произойдет следующее. Нам срочно нужно освободить для этой буквы какое-то пространство, сдвинув все остальные буквы на один символ вперёд. Для этого мы сдвигаем эту букву на одну позицию, потом следующую и так далее, до самого конца текста.

    Вот как это будет выглядеть в памяти:



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

    Чтобы решить эту проблему вставки символа в середину, давным-давно придумали обходной манёвр под названием «Gap Buffer».

    Gap Buffer


    Gap — это зазор. Buffer — это, как вы догадываетесь, буфер. Структура данных «Gap Buffer» — это такой пустой буфер, который мы храним посередине нашего текста, на всякий случай. Если нам потребовалось что-то напечатать, мы используем этот текстовый маленький буфер для быстрого впечатывания.



    Структура данных у нас немножко поменялась — массив остался на месте, но появились два указателя: на начало буфера и на его конец. Чтобы взять символ из редактора по какому-то смещению, нам нужно понять, находится ли он до или после этого буфера и немножечко подправить смещение. А чтобы вставить символ, нам нужно сначала пододвинуть Gap Buffer к этому месту и заполнить его этими символами. И, конечно, если мы вышли за пределы нашего буфера, его как-то пересоздать. Вот как это выглядит на картинке.



    Как видно, мы сначала долго двигаем на маленький gap-buffer (синенький прямоугольник) к месту редактирования (просто меняя местами символы с его левого и правого края по очереди). Потом мы используем этот буфер, впечатывая туда символы.

    Как можно заметить, никакого передвижения мегабайт символов нет, вставка происходит очень быстро, за константу времени, и вроде все счастливы. Кажется, всё хорошо, но если у нас процессор очень медленный, то на перемещение туда-сюда gap-buffer и текста тратится довольно заметное время. Особенно это было заметно во времена очень маленьких мегагерц.

    Piece Table


    Как раз в это время корпорация под названием Microsoft писала текстовый редактор Word. Они решили применить у себя другую идею для ускорения редактирования под названием «Piece Table», то есть «Таблица Кусочков». И они предложили текст редактора сохранять в этом же самом простейшем массиве символов, который меняться не будет, а все его изменения складывать в отдельную таблицу из этих самых отредактированных кусочков.



    Таким образом, если нам нужно найти какой-то символ по смещению, нам нужно найти этот кусочек, который мы поредактировали, и извлечь из него этот символ, а если его там нет, то пойти в оригинальный текст. Вставка символа становится легче, нам всего лишь нужно этот новый кусочек создать и добавить в таблицу. Вот как это выглядит на картинке:



    Здесь мы захотели удалить пробел по смещению 5. Для этого мы добавляем в таблицу кусочков два новых кусочка: один указывает на первый фрагмент («Облом»), а второй указывает на фрагмент после редактирования («овцы»). Получается, что пробел из них исчезает, эти два кусочка склеиваются, и у нас получается новый текст уже без пробела: «Обломовцы». Потом добавляем новый текст («страдающие обломовщиной») в конец. Используем дополнительный буфер и добавляем в таблицу кусочков (piece table) новый кусочек, который указывает на этот самый новый добавленный текст.

    Как видите, никаких перемещений туда-сюда не происходит, весь текст остаётся на месте. Плохо то, что становится сложнее добраться до символа, потому что перебирать все эти куски довольно тяжело.

    Подведем итоги.

    Что хорошо в Piece Table:

    • Быстро вставлять;
    • Легко сделать undo;
    • Append-only.

    Что плохо:

    • Ужасно сложно обращаться к документу;
    • Ужасно сложно реализовать.

    Давайте посмотрим, кто у нас вообще обычно что использует.

    NetBeans, Eclipse и Emacs используют Gap Buffer — молодцы! Vi не заморачивается и использует просто список строчек. Word использует Piece Table (недавно они выложили свои древние сорцы и там даже можно что-то понять).

    С Atom интереснее. До недавнего времени они не заморачивались и использовали JavaScript-список строчек. А потом решили всё переписать на C++ и наворотили довольно сложную структуру, которая вроде как похожа на Piece Table. Но вот эти кусочки у них хранятся не в списке, а в дереве, причём в так называемом splay tree — это дерево, которое саморегулируется при вставке в него, чтобы недавние вставки были быстрее. Очень сложную штуку они наворотили.

    Что использует Intellij IDEA?
    Нет, не gap-buffer. Нет, вы тоже не правы, не piece table.
    Да, совершенно верно, свой собственный велосипед.

    Дело в том, что у IDE требования к хранению текста немного другие, нежели в обычном текстовом редакторе. Для IDE нужна поддержка разных хитрых вещей вроде конкуррентности, то есть параллельного доступа к тексту из редактора. Например, чтобы много разных испекшенов могли его читать и что-то делать. (Инспекшн — маленький кусочек кода, анализирующий программу тем или иным образом, — например, ищущий места, выбрасывающие NullPointerException). Также для IDE нужна поддержка версий редактируемого текста. Несколько версий одновременно лежат в памяти, пока вы работаете с документом, с тем, чтобы эти долгие процессы продолжали анализировать старую версию.

    Проблемы


    Конкуррентность / Версионность


    Для того, чтобы поддержать параллельность, операции с текстом обычно оборачивают в «synchronized», или в Read-/Write-локи. К сожалению, это всё не очень хорошо масштабируется. Другой подход — Immutable Text, то есть неизменяемое хранилище текста.



    Вот как выглядит редактор с неизменяемым документом в качестве поддерживающей структуры данных.

    Как устроена сама структура данных?

    Вместо массива символов у нас будет новый объект типа ImmutableText, хранящий текст в виде дерева, где в листах хранятся маленькие подстрочки. При обращении по какому-то смещению он пытается в этом дереве дойти до самого нижнего листа, и у него уже спросить символ, к которому мы обращались. А при вставке текста он создает новое дерево и сохраняет его в старом месте.



    К примеру, у нас есть документ с текстом «Бескалорийный». Он реализован как дерево с двумя листами из подстрочек «Бес» и «калорийный». Когда мы хотим вставить в середину строчку «довольно», то создается новая версия нашего документа. И именно, создается новый корень, к которому привязываются уже три листа: «Бес», «довольно» и «калорийный». Причём два из этих новых листов могут ссылаться на первую версию нашего документа. А для листа, в который мы вставили строчку «довольно», отводится новая вершина. Тут и первая версия, и вторая версии доступны одновременно и они все иммутабельные, неизменяемые. Всё выглядит хорошо.

    Кто же использует какие хитрые структуры?



    Вот, например, в GNOME какой-то их стандартный виджет использует структуру под названием Rope. Xi-Editor — это новый блестящий редактор от Рафа Левиена — использует Persistent Rope. А Intellij IDEA использует этот самый Immutable Tree. За этими всеми названиями, на самом деле, скрывается более-менее одна и та же структура данных с древовидным представлением текста. За исключением того, что GtkTextBuffer использует Mutable Rope, то есть дерево с изменяемыми вершинами, а Intellij IDEA и Xi-Editor — Immutable.

    Следующая вещь, которую нужно учитывать при разработке хранилища символов в современных IDE, называется «мультикаретки». Эта фича позволяет печатать сразу в несколько мест, используя несколько кареток.



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



    Если мы вставляем символ в наш самый первый примитивный редактор, для этого потребуется, естественно, линейное количество времени, чтобы сдвинуть туда-сюда кучу символов. Это записывается в виде O(N). Для редактора на основе Gap Buffer’а, в свою очередь, требуется уже константное время, для этого он и был придуман.

    Для immutable-дерева время зависит логарифмически от размера, потому что надо сначала пройти от вершины дерева до его листа — это логарифм, а потом для всех вершин на пути создать новые вершины для нового дерева — это опять логарифм. Для Piece Table тоже требуется константа.
    Но все немножко меняется, если мы попробуем померять время вставки символа в редактор с мульти-каретками, то есть, вставки одновременно в несколько мест. С первого взгляда, время вроде как должно пропорционально увеличиться в C раз — число мест, куда вставляется символ. Всё так и происходит, за исключением Gap Buffer’а. В его случае время, вместо C раз, неожиданно увеличивается какое-то непонятное C*L раз, где L — среднее расстояние между каретками. Почему так происходит?

    Представим, что нам надо вставить строчку «, на» в два места в нашем документе.



    Вот что происходит в редакторе в это время.

    • Создаем в редакторе gap-buffer (синенький прямоугольничек на рисунке);
    • Заводим две каретки (черные жирные вертикальные черты);
    • Пробуем печатать;
    • Вставляем запятую в наш Gap Buffer;
    • Должны теперь вставить её в место второй каретки;
    • Для этого нам нужно пододвинуть наш Gap Buffer до положения следующей каретки;
    • Впечатываем запятую во второе место;
    • Теперь нужно вставить следующий символ в положение первой каретки;
    • И мы должны пододвинуть наш Gap Buffer обратно;
    • Вставляем букву «н»;
    • И двигаем наш многострадальный буфер в место второй каретки;
    • Вставляем туда нашу «н»;
    • Двигаем буфер обратно, чтобы вставить следующий символ.

    Чувствуете, к чему все идет?

    Да, получается, что из-за этих многочисленных телодвижений буфера туда-сюда наше общее время увеличивается. Честно говоря, не то чтобы оно прямо ужас как увеличилось, — подвинуть жалкие мега-, гигабайты туда-сюда для современного компьютера не проблема, но всё равно интересно, что эта структура данных в случае мультикареток работает радикально по-другому.

    Слишком много строчек? LineSet!


    Какие еще есть проблемы в обычном текстовом редакторе? Самая сложная проблема — это скроллинг, то есть перерисовка редактора во время передвигания каретки на следующую строчку.



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



    Для этого есть очевидный интерфейс, когда мы по номеру строчки должны понять её смещение в тексте. И наоборот, по смещению в тексте понять, в какой строчке оно находится. Как это можно быстро сделать?

    Например, так:

    Организовать эти строчки в дерево и каждую вершину этого дерева разметить смещением начала строки и смещением конца строки. И тогда, чтобы по смещению понять, в какой строке оно находится, просто нужно запустить логарифмический поиск в этом дереве и найти его.



    Другой способ ещё проще.

    Записать в таблицу смещение начала строчек и конца строчек. И тогда, чтобы по номеру строки найти смещение начала и конца, нужно будет обратиться по индексу.



    Что интересно, в реальном мире используется и тот, и другой способ.



    Например, Eclipse использует такую деревянную структуру, которая, как видно, работает за логарифмическое время и на чтение, и на обновление. А IDEA использует табличную структуру, для которой чтение — это быстрая константа, — это обращение по индексу в таблице, но зато перестроение — довольно медленное, потому что нужно всю таблицу перестроить при изменении длины какой-то строчки.

    Всё ещё слишком много строчек? Foldings!


    Что ещё есть плохого, на что натыкаются в текстовых редакторах? Например, фолдинги. Это кусочки текста, которые можно «схлопнуть» и показать вместо них что-то другое.



    Вот эти вот многоточия на зелёном фоне на картинке скрывают позади себя много символов, но, если нам их смотреть неинтересно (как в случае, например, длиннейших скучных Java-doc’ов или импорт-листов), мы их скрываем, схлопываем в это самое многоточие.

    И тут опять нужно понять, когда заканчивается и когда начинается регион, который нам нужно показать, и как это всё быстро обновлять? Как это организовано, расскажу чуть позже.

    Слишком длинные строчки? Soft wrap!




    Также современные редакторы не могут жить без Soft wrap. На картинке видно, что разработчик открыл JavaScript-файл после минимизации и сразу об этом пожалел. Вот эта огроменнейшая JavaScript-строка, когда мы её пытаемся показать в редакторе, ни в какой экран не влезет. Поэтому soft wrap ее принудительно разрывает на несколько строчек и впихивает в экран.
    Как это организовано — позже.

    Слишком мало красоты




    И, наконец, хочется ещё в текстовых редакторах навести красоту. Например, подсветить некоторые слова. На картинке выше ключевые слова подсвечены синим жирным, какие-то static методы италиком, какие-то аннотации — тоже другим цветом.

    Так как же все-таки хранить и обрабатывать фолдинги, софт-врапы и хайлайтинги?
    Оказывается, что всё это, в принципе, — одна и та же задача.

    Слишком мало красоты? Range highlighters!




    Чтобы поддержать все эти фичи, всё, что нам нужно уметь — это по данному смещению в тексте прилепить какие-то текстовые атрибуты, например, цвет, шрифт или текст для фолдинга. Причем эти текстовые атрибуты надо всё время обновлять на этом месте, чтобы они переживали всякие вставки и удаления.

    Как это обычно реализуется? Естественно, в виде дерева.

    Проблема: слишком много красоты? Interval tree!




    Вот, например, у нас тут есть несколько жёлтых подсветок, которые мы хотим сохранить в тексте. Мы складываем интервалы этих хайлайтингов в дерево поиска, так называемое интервальное дерево. Это то же самое дерево поиска, но немного хитрее, потому что нам надо хранить интервалы вместо числа.

    А так как есть как здоровые, так и маленькие интервалы, то как их сортировать, друг с другом сравнивать и складывать в дерево — довольно нетривиальная задача. Хотя и очень широко известная в computer science. Посмотрите потом как-нибудь на досуге, как оно устроено. Так вот, берём и складываем все наши интервалы в дерево, и потом каждое изменение текста где-нибудь посередине приводит к логарифмическому изменению этого дерева. Например, вставка символа должна привести в обновлению всех интервалов справа от этого символа. Для этого мы находим все доминантные вершины для этого символа и указываем, что все их подвершины надо отодвинуть на один символ вправо.

    Ещё хочется красоты? Ligatures!




    Ещё есть такая страшная штуковина — лигатуры, которую тоже бы хотелось поддержать. Это разные красоты вроде того, как знак «!=» рисуется в виде большого глифа «не равно» и так далее. К счастью, тут мы рассчитываем на свинговый механизм поддержки этих лигатур. И, по нашему опыту, он, видимо, работает наипростейшим образом. Внутри шрифта хранится список всех этих пар символов, которые, соединяясь вместе, образуют какую-то хитрую лигатуру. Потом, при отрисовке строчки, Swing просто перебирает все эти пары, находит нужные и рисует их соответствующим образом. Если у вас в шрифте очень много лигатур, то, видимо, отображение его будет пропорционально тормозить.

    Тормозит тайпинг


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



    Если залезть внутрь Intellij IDEA и посмотреть, что происходит при нажатии какой-то кнопки, то там происходит, оказывается, следующий ужас:

    • При нажатии кнопки мы должны посмотреть, не находимся ли мы в completion popup’е, чтобы закрыть меню для completion’а, если мы, например, впечатываем какой-нибудь «Enter».
    • Нужно посмотреть, находится ли файл под какой-то хитрой системой контроля версий, вроде Perforce, которая должна сделать какие-то действия для начала редактирования.
    • Проверить, есть ли какой-то специальный регион в документе, в котором нельзя печатать, вроде каких-нибудь автогенерированных текстов.
    • Если документ заблокирован операцией, которая не закончилась, нужно завершить форматирование, и только потом продолжить.
    • Найти injected-документ, если он имеется в этом месте, потому что язык в нём будет другой, нужно совсем по-другому всё впечатывать.
    • Вызвать у всех плагинов auto popup handler, чтобы они могли впечатать, например, закрывающую и открывающую кавычку в нужном месте.
    • Для параметров info обновить окошечко, чтобы оно показывало нужные параметры, если мы туда переместились. У этих плагинов вызвать selection remove, чтобы они удалили selection нужным образом, зависящим от языка. И убрать этот selection физически, удалив его из документа.
    • Выбрать у всех плагинов typed handler, чтобы они обработали нужный символ для того, чтобы напечатать скобку поверх другой скобки.
    • Закрывающую структурную скобку обработать.
    • Запустить undo, подсчитать virtual space’ы и запустить write action.
    • Наконец, вставить символ в наш документ.

    Ура!

    Черт, нет, это не всё. Удалить символ, если наш буфер переполнился. Например, в консоли вызвать listener для того, чтобы все знали, что что-то поменялось. Отскроллить editor view. Вызвать какие-то ещё дурацкие listener’ы.

    И что теперь происходит в редакторе, когда он узнал, что документ-то у нас поменялся и вызвался DocumentListener?

    В Editor.documentChanged() происходит вот что:

    • Обновить error stripe;
    • Пересчитать gutter size, перерисовать;
    • Пересчитать editor component size, послать эвенты при изменении;
    • Подсчитать измененные строки и их координаты;
    • пересчитать soft wrap, если изменение его затронуло;
    • Вызвать repaint().

    Этот repaint() — это просто указание для Swing, что данный регион на экране должен быть перерисован. Настоящая перерисовка произойдет, когда событие Repaint будет обработано очередью сообщений Swing.

    То есть где-то через полчаса подойдет очередь обработки нашего события, вызовется метод repaint у соответствующей компоненты, который будет делать следующее:



    Вызывается куча разных paint-методов, которые рисуют всё, что только возможно на свете в этом случае.

    Ну что, может, соптимизируем это всё?



    Это всё, мягко говоря, довольно сложно. Поэтому мы в Intellij IDEA решили обмануть пользователя.



    Перед всякими этими ужасами, которые что-то пересчитывают и что-то записывают, мы вызываем маленький метод, который рисует эту несчастную букву прямо на том месте, куда пользователь её впечатывает. И всё! Пользователь счастлив, потому что он думает, что уже всё поменялось, а на самом-то деле — нет! Под капотом всё ещё только начинается, но буковка-то уже перед ним горит. И поэтому все довольны. Эта фича у нас называется «Zero latency typing».

    Коллаборативные редакторы


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

    Что это такое? Это когда один пользователь сидит в Индии, другой — в Японии, они пытаются в один и тот же Google Docs что-то напечатать и хотят какого-то предсказуемого результата.

    Что особенного:

    • Тысячи пользователей;
    • Большая задержка.

    Особенность тут такая, что огромное число пользователей это может делать одновременно, и сигнал очень долго может идти из Индии в Японию.

    И из-за этого обычно в коллаборативных редакторах используют новомодные вещи вроде иммутабельности. И придумали разные вещи, как убедиться, что всё работает как нужно. Это несколько критериев. Первый критерий — это сохранение интенции, «intention preservation». Это значит, что если кто-то впечатал символ, то рано или поздно символ из Индии приплывёт в Японию, и японец увидит именно то, что задумал индиец. И второй критерий — конвергенция. Это значит, что символы из Индии и Японии рано или поздно преобразуются во что-то одно и то же и для Японии, и для Индии.

    Operation transformation




    Первый алгоритм, который был придуман для поддержки этой штуковины, называется «operation transformation». Он работает так. Сидят индиец и японец, что-то печатают: один удаляет с конца букву, другой пририсовывает букву в начало. Фреймворк Operation transformation посылает эти операции во все другие места. Он должен понять, как нужно смержить операции, приходящие к нему, чтобы получилось хоть что-нибудь здравомыслящее. Например, когда у вас одновременно буква удалилась и появилась. Он должен и там, и там отработать более-менее консистентно и прийти к одной и той же строчке. К сожалению, как видно из моего путаного объяснения, это дело довольно сложное.

    Когда стали появляться первые реализации этого фреймворка, изумленные разработчики обнаружили, что есть универсальный пример, который все ломает. Этот злополучный пример назвали «TP2 puzzle».



    Один пользователь пририсовывает в начало строчки какие-то символы, другой всё это удаляет, а третий пририсовывает в конец. После того, как это всё Operation transformation пытается слить в одно и то же, то должна, по идее, получиться вот эта строчка («ДАНА»). Однако некоторые имплементации делали вот такую («НАДА»). Потому что непонятно, куда вставлять нужно. На картинке выше видно, на каком уровне находится вся эта наука про Operation transformation, если из-за такого примитивного примера у них всё ломалось.

    Но несмотря на это некоторые люди всё равно это делают, вроде Google Docs, Google Wave и какого-то распределённого редактора Etherpad. Они используют Operation transformation несмотря на перечисленные проблемы.

    Conflict-free replicated data type


    Люди тут пораскинули мозгами и решили: «Давайте сделаем проще, чем OT!» Число всяких хитрых сочетаний операций, которые нужно обрабатывать и сливать вместе, растет квадратично. Поэтому, вместо того, чтобы обрабатывать все сочетания, мы будем просто отправлять своё состояние вместе с операцией всем другим хостам таким образом, чтобы можно было с гарантией 100% это всё слить в один и тот же текст. Это называется «CRDT» (Conflict-free replicated data type).



    Чтобы это работало, нужно состояние и функция, которая из двух состояний вместе с операцией делает новое состояние. Причем, эта функция должна быть коммутативной, ассоциативной, идемпотентной и монотонной. И тогда понятно, что всё будет работать просто и железобетонно. Из-за этих драконовских ограничений на функцию нам теперь не страшны нарушения порядка (функция ж коммутативна), приоритета (ассоциативна) и потери пакетов в сети (идемпотентность и монотонность).



    Есть ли в природе такие функции и как их можно применить?

    Да. Например, для случая так называемых G-counter’ов, то есть счетчиков, которые только растут. Можно написать для этого счетчика функцию, которая действительно будет монотонной и так далее. Потому что если у нас есть операция «+1» из Японии, другая «+1» из Индии, понятно, как из них сделать новое состояние — просто прибавить «2». Но оказывается, что таким же образом можно делать ещё и произвольный счетчик, который можно инкрементировать и декрементировать. Для этого достаточно взять один G-counter, который растёт всё время вверх, и все операции инкремента применять к нему. А все декременты применять к другому G-counterу, который будет расти вниз. Чтобы получить актуальное состояние, нужно просто вычесть их содержимое, и у нас получится та самая монотонность. Это всё возможно распространить на произвольные множества. Но самое главное — на произвольные строки. Да, редактирование произвольных строк тоже можно сделать CRDT. Оказывается, это довольно легко.

    Conflict-free replicated inserts




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

    Теперь вместо того, чтобы отправлять всем людям информацию, что мы вставляем по какому-то смещению какой-то символ, мы, вместо этого, будем говорить, между какими именно символами мы будем это вставлять. И тогда понятно, что никаких разночтений быть не может, куда бы мы ни вставляли, мы точно будем знать место, даже после всяких других операций. Вот, например, вместо того, чтобы посылать операцию о том, что мы по смещению 2 мы хотим вставить «РЖУ», мы будем посылать информацию, что между этой «У» и этой «Й» мы вставляем «РЖУ».

    Conflict-free replicated deletes




    Также можно реализовать и удаление символов. Так как у нас все символы уникально переименованы, мы просто говорим точно, какой именно символ нужно удалить, вместо каких-то смещений. Но вместо того, чтобы взять и физически удалить эти символы, мы будем их помечать удалёнными. Для того, чтобы последующие параллельные вставки или удаления знали, если они затронут эти удалённые только что символы, куда именно им обращаться.
    И получается, что эта вся новомодная наука работает.

    Conflict-free replicated edits


    И, на самом деле, CRDT даже где-то реализовано, например, в Xi-Editor, который будет вставлен в их новомодную секретную операционную систему Fuchsia. Честно говоря, других примеров я не знаю, но это точно работает.

    Zipper


    Ещё хотел бы рассказать о штуке, которая используется в этом новом иммутабельном мире под названием «Zipper». После того, как мы свои структуры сделали неизменяемыми, появились некоторые нюансы работы с ними. Вот, к примеру, у нас есть наше иммутабельное дерево с текстом. Нам хочется его поменять, (под «поменять» здесь, как вы понимаете, я имею в виду «создать новую версию»). Причем, нам хочется его менять в каком-то определённом месте и довольно активно. В редакторах это довольно часто встречается, когда в месте курсора мы постоянно что-то печатаем, вставляем и удаляем. Для этого функциональщики придумали структуру под названием Zipper.

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



    Создаём Zipper для нашего документа, который содержит строку для редактирования («Ну надо же»). Вызываем операцию на этом Zipper’е для перемещения по строке в место редактирования. В нашем случае — спуститься на вершину вправо вниз. Для этого мы создаем новую вершину (красненькую), соответствующую текущей вершине, прикрепляем к ней ссылки на дочерние вершины из нашего дерева. Теперь, чтобы переместить курсор Zipperа, мы спускаемся вправо-вниз и создаем также создаем новую вершину вместо той, на которой стояли. При этом, добавляем ссылку на вершину вверх, чтобы не забыть, откуда пришли (красные стрелки). Дойдя таким образом до места редактирования, мы создаем новый лист взамен поредактированного текста (красный прямоугольник). Теперь возвращаемся назад, идя по красным стрелкам вверх и заменяя их по пути на правильные ссылки на дочерние вершины. Когда дойдем до вершины, у нас получится новое дерево с отредактированным листом.

    Обратите внимание, как курсор помогает нам редактировать текущий кусочек дерева.

    Какие выводы я хотел до вас донести? Во-первых, как ни странно, в теме текстовых редакторов, несмотря на её затхлость, существуют всякие интересные вещи. Более того, в этой же теме появляются иногда новые, иногда неожиданные открытия. И в-третьих, иногда они настолько новые, что не работают с первого раза. Зато интересно и можно согреться. Спасибо.

    Репозиторий
    Почта

    Ссылки


    Zipper data structure
    Как устроен CRDT in Xi Editor
    И вообще о древовидных структурах данных для текста
    Что наворотили в Атоме

    После доклада прошло много времени, и Микрософт успел вспомнить о своих корнях и переписать Visual Studio Code editor на Piece Table.
    И вообще, многих людей почему-то потянуло на эксперименты.

    Хотите ещё больше мощных докладов, в том числе и о Java 11? Тогда ждём вас на Joker 2018. В этом году выступят: Джош Лонг, Джон МакКлин, Маркус Хирт, Роберт Шольте и другие не менее крутые спикеры. До конференции осталось 17 дней. Билеты на сайте.

    JUG.ru Group

    644,00

    Конференции для взрослых. Java, .NET, JS и др. 18+

    Поделиться публикацией
    Комментарии 188
      +10
      Тут снискала популярность демагогичная статья habr.com/post/423889.

      Надеюсь эта статья хоть не много объяснит людям почему современные редакторы кода и текста требуют больше ресурсов чем раньше.
      И что за удобство и фичи надо платить производительностью.
        +3

        Не объяснила. Перечисленные фичи есть в редакторах со времен 90х. Хотя статья любопытная.

          +18
          Статический анализ кода, умный рефакторинг по гигантскому проекту и прочее, есть с 90x?

          Зачем же тогда люди придумывали Python и прочие языки без бойлерплейта, если еще тогда можно было с помощью редакторов вести быструю разработку на статически типизированных языках?
            –3
            Статический анализ кода

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


            Умный рефакторинг

            LISP ещё в 60х был придуман. Но если серьёзно, то я сомневаюсь в слове "умный" относительно современных средств. Sed знающий семантику языка? Ну это мягко говоря не очень умный и не очень продвинутый.

              +13

              Сразу видно, что IDE вроде IDEA или VS+ReSharper вы не пользуетесь.


              Sed знающий семантику языка?
              Да даже синтаксис в иерархии Хомского на другом уровне сложности. А семантика тем более. Я ещё не говорю про data flow analysis и т.п.
                +2
                Сразу видно, что вы не умеете нормально пользоваться текстовыми редакторами P.S. я пользуюсь IDEA и emacs в зависимости от проектов и emacs не сильно проигрывает по фичам IDEA, зато жрет памяти и нагружет процессор намного меньше, если emacs может кушать 150 МБ, то IDEA будет может кушать 2-4 ГБ., а если это android studio то и все 16 ГБ сожрет.
                  –6
                  У вас память по талонам?
                    +3
                    У меня всего 16. АндроидСтудио с проектом, браузер с документацией пичарм с локальным сервером. И вот пуская прилагу в эмуляторе я периодически вижу что система пошла активно свопится, что даже на ssd очень не приятно. И я как то не понимаю почему мои задачи не сильно отличаются от от задач 2-3 летней давности, но тогда памяти было с избытком а сейчас в притык стало.

                    И если в свой системник я без проблем пойду и докуплю еще плашку, то вот в макбук я их не поставлю.
                      0
                      В моём ноуте память запаяна и там её 8ГБ, например. Не то чтобы я собирался использовать IDEA, конечно — мне и VimR хватает.
                      0
                      > не сильно проигрывает по фичам IDEA
                      Как в emacs со 150МБ переместить метод и класса A в класс B?
                        0
                        для питона например есть rope: github.com/python-rope/ropemacs
                          0
                          И что, при открытии исходников TensorFlow в emacs с установленным rope, это всё потребляет только 150МБ?
                        +3
                        Сразу видно, что вы не умеете нормально пользоваться текстовыми редакторами P.S

                        Сразу видно, вы не умеете нормально пользоваться ide и не представляете, что происходит, когда вы делаете ide из emacs/vim/sublime.


                        Все ide'шные штуки в духе автодополнение, линтинга, рефакторинга запускаются сторонними процессами и интегрированы так плохо, что жрут в сумме куда больше чем ide, и еще обладают феерическими багами из-за которых их приходится по два раза в день перезапускать.


                        А если вам нужен только текстовый редактор, то разумеется, что idea тут будет проигрывать…

                          +2
                          интегрированы так плохо, что жрут в сумме куда больше чем ide

                          А вы как давно пробовали? Сегодня есть классная штука — language server, и по моим ощущением (опять же, если сам language server реализован нормально, что пока не всегда правда но это дело наживное) какой-нибудь neovim + language server для какого-нибудь typescript работает получше нежели всякие там webstorm.


                          Я лично жизнь не представляю без IDE, особенно для языков типа Java или, в моем случае, PHP. Но помимо "редакторы с плагинами жрут больше чем IDE с плагинами" я бы скорее сказал что проблема в другом — я просто привык к продуктам jetbrains за 5 лет. И как-то тот же vscode мне пока дается с трудом. А перелесть на neovim я так и не смог (хотя пытался). И дело не в том что мне не хватает каких-то фич (каких-то не хватает, но не могу сказать что они координально влияли на мою продуктивность) а скорее в том что речь о выходе из зоны комфорта.


                          Но в целом тренды (тот же language server) мне нравится. Помню лет 5 назад когда поднималась популярность такого языка как D многие не хотели его пробовать банально в связи с отсутствием поддержки оного в какой-либо из IDE. Гиганты вроде Jetbrains инвестировать в подобное будут только, если на это есть существенный спрос, которого нет потому что нет инструментов. Да и опять же, штуки типа рефакторинг браузер под каждый редактор имплементить как-то странно. А так — запилили бы ребята из команды разработчиков D сразу language server поставляемый вместе с компилятором, и вжух — у всех все есть, все новые фичи всегда доступны вместе с обновлением компилятора, и язык продвигать можно и много чего еще.


                          Или, скажем, PHP. Не секрет что PHP как язык убожество. И что бы это минимально исправить существуют проекты типа yay и preprocess.io. Вот только ждать суппорта IDE для таких вещей глупо, что тормозит развитие таких идей. А был бы language server — да в том же шторме люди могли бы пользоваться на равне с людьми которые привыкли к vi.

                            0
                            Минут пять назад в таком код пишу :)

                            Ну вот anaconda для python в sublime так работает. Но вот только не реализовано практически ничего, кроме интеграции с внешними тулзами, такими как jade для автодополнения, pyflakes (или другие на выбор) для линтера кода и так далее.

                            В целом реализация классная, но существует целый ряд проблем:
                            1. Иногда языковые сервера для проектов не переключаются
                            2. Нет возможности как-то промониторить его состояние, так что любой тупняк чинится перезапуском sublime.
                            3. Тупняки на больших проектах, потому что линтеры то не держать в памяти код

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

                            Ну и написать language server это тоже довольно сложно и затратно и как обычно будет, что у каждого текстового редактора будет какой-то свой стандарт или проблемы совместимости и приехали.

                            Опять таки, редактор, который популяризировал именно название languge server, если не ошибаюсь vscode, этим парням тоже не нравятся.

                            К вопросу, а почему sublime в качестве примера, у других редакторов большие проблемы с работой с python интепретатором в docker контейнере.
                            0
                            я хорошо знаю свои инструменты, в том числе и ide, которыми пользуюсь, я писал выше, что не дотягивает по фичам, но и не сильно таки уступает, по поводу отжора памяти не замечал ничего подобного, у меня старый ноутбук, на котором всего 2ГБ оперативки + всякие language server линтенры и прочее работают и все это съедает около 200-400МБ максимум (вместе с emacs'ом). Когда я выбираю emacs или IDEA (другие IDE я не воспринимаю), я всегда смотрю на то как хорошо IDEA поддерживает язык, и если все супер, конечно же я использую IDEA, потому-что действительно много удобных фичей, теже тайп хинты, override, implement, работа с бд итд, но если язык плохо поддерживается или поддержка языка слишком уж убогая и тормозная, то я предпочту использовать emacs. Лично я для Java, Kotlin, Python использую IDEA, для go и D только emacs. Главное настроить все надо, а сделать из emacs удобный и приятный инструмент довольно не простая задача.
                              +1
                              специально только что проверил, режим в emacs'е для D вместе с языковым сервером, линтером, автоформатером и прочими дополнительными скриптами отъедает 220 МБ оперативной памяти. Для сравнения intellij idea 1.2 ГБ, и время от времени циферка увеличивается.
                                +1

                                Поддержка Go в Идее за последний год улучшилась просто на порядок. В неё реально вложились. Если пробовали давно, попробуйте снова :-)

                                  0
                                  Попробую, но в последний раз goland мне просто удалил кусок кода )
                            0
                            И если вы, предположим, будете писать на Java в Emacs какой-то SQL запрос в строке, например String sql = «SELECT id, name FROM table»;, то он сможет в автокомплит кусков SQL запроса, основываясь на настроенном подключении к БД и знании синтаксиса данного конкретного SQL диалекта?
                              0
                              Не знаю, может есть какие-то плагины для emacs'а с такими фичами. Но вангую что нет, и выше я уже писал что emacs по фичам проигрывает, но тем не менее вполне себе можно создать из него IDE.
                        +3
                        Atom умудряется тормозить и без всего этого.
                          +1
                          Кстати, VSCode «со всем этим» нa удивление довольно шустрый.
                            0
                            Относительно чего? Тот же Sublime Text работает ощутимо быстрее.

                            В VS Code субъективно неприятно открывать на редактирование по одному файлу, только целыми директориями/проектами. Но тогда времени уже не жалко на открытие полноценной IDE.

                            (Да-да-да, давний холивар, который обычно оканчивается на том, что в ST нет тех самых хайповых плагинов, которые нужны одной из сторон)
                              0
                              Относительно чего? Тот же Sublime Text работает ощутимо быстрее.

                              Ну так Саблайм — это по сути просто модный блокнот, а ВСКод — и есть «полноценная IDE» со статическим анализом, интелисенсом, дебагером, контролем версий и прочими плюшками. И все это из коробки.
                                +1

                                О_о. Разве это всё не обеспечивается предустановленными плагинами, многим из которых есть аналоги в sublime? По сути это два, во многом идентичных редактора, а не IDE, к которым плагинами можно прицепить доп. функциональность.

                                  +1
                                  Есть разница между функциональностью из коробки и функциональностью плагинов. Первая обычно гораздо лучше поддерживается, обновляется и т.д. Все что я перечислил в предыдущем комментарии в VSCode реализовано гораздо лучше чем то что предоставляют плагины в Sublime.
                                  Сам долго не мог слезть с Саблайма из-за его отличной производительности, но фичи взяли свое.
                                  Фишка VSCode в том что это именно «IDE из коробки», а не просто редактор с плагинами.
                                    0

                                    Наверное вы используете какой-либо статически типизированный язык. Я пишу на pure JS и никаких хитрых фишек IDE в vsCode не увидел. По сути для меня оба эти редактора, как вы выразились, "просто модные блокноты". По воле случая сейчас работаю сразу в обоих :)

                                      0
                                      Ну pureJS в принципе трудно анализировать, но многие библиотеки написаны s использованием jsdoc, а это хоть как-то помогает.
                                        0

                                        Да я обратил внимание на то, что intellisence тут посильнее и иногда я вижу какие-то аннотации, при использовании внешних библиотек с тайпингами для TS. В остальном плюс минус одно и то же.


                                        Наверное, резюмируя, правильнее будет сказать что да, vsCode это IDE для TS, но всё ещё "модный блокнот" для всех остальных языков\окружений.

                                  0
                                  Плагины ведь есть. VS Code из коробки поддерживает отладку и исполнение только NodeJS. Но ведь медленно запускается даже на холодную, без задействования вот этого всего функционала.
                                    0
                                    Не только NodeJS, но в принципе JavaScript/TypeScript проектов, в том числе чисто «фронтовых» (анализ тайпскрипта так вообще пока лучше не видел, все-таки одна компания делает).
                                    Т.е. по сути хорошая альтернатива тому жe WebStorm'у, и сравнивать его с легковесными редакторами не корректно.

                                    ПС на моем макбуке 2015го запускается за 3-4 секунды обычно, считаю это вполнe неплохо для «ide на электроне»
                                      0
                                      Не только NodeJS, но в принципе JavaScript/TypeScript проектов

                                      Учитывая, что эти языки тесно связаны одной сферой применения, то преимущества выходят достаточно нишевыми.

                                      запускается за 3-4 секунды обычно, считаю это вполнe неплохо для «ide на Электроне»

                                      Для редактора кода, кмк, это очень долго (если хочется тыкнуть в пару файлов, поправить коммит-сообщение в Git или что-то такое оперативное, для чего не потребуется запускать IDE). Но крайняя ремарка, конечно, все расставляет на свои места.

                                      То есть это бесплатная, упрощенная альтернатива WebStorm. Не серебряная пуля, которая могла бы подойти каждому программисту.
                                        0
                                        То есть это бесплатная, упрощенная альтернатива WebStorm. Не серебряная пуля, которая могла бы подойти каждому программисту.

                                        Я бы не назвал ее «упрошенной». По сути функциональность сопоставима. К тому же у VSCode есть «language server» который легко позволяет добавлять поддержку других языков, a не скачивать еще одну ide. (https://code.visualstudio.com/docs/languages/overview)
                                        Например я сейчас использую его для проекта на Python, и не могу сказать что нет чего-то необходимого, что есть в PyCharm.
                                          0
                                          у VSCode есть «language server» который легко позволяет добавлять поддержку других языков, a не скачивать еще одну ide.

                                          А как же компиляторы/рантаймы, системы сборки, пакетные менеджеры, шаблоны проектов и поддержка всего этого добра в редакторе? Это все нужно будет ставить отдельно, собирать по разнородным плагинам, с километрами непереносимых конфигов. При таких раскладах можно брать допотопный Vim/Emacs и строить на нем то же самое.

                                          Все же проще скачать IDE.
                                            0
                                            компиляторы/рантаймы, системы сборки

                                            покрывает language server
                                            пакетные менеджеры, шаблоны проектов

                                            Пакетные менеджеры насколько я знаю пока не поддерживаются, но запланированы. Шаблоны проектов на мой взгляд не маст хэв фича для иде, только если это под какую-то конкретную платформу (xcode, android studio)

                                            Все же проще скачать IDE.

                                            ХЗ, например тот же вебшторм ничего кроме JS/HTML/CSS нормально нe поддерживает, a часто бывает что бекенд (написанный на node/ruby/python/php/...) и фронт находятся в одном проекте и проще установить поддержку языка чем юзать две разные IDE для фронта и бека.
                                            К тому же vscode сам, когда обнаруживает в проекте не поддерживаемый язык — предлагает его установить.
                                            0
                                            Я вам скажу, чего нет. Возможности работы с интерпретатором, который в docker контейнере.
                              +1
                              Снова путают статическую типизацию и явные аннотации типов с прочим бойлерплейтом. Грустно.
                                0
                                Бойлерплейт-код

                                Код, не описывающий непосредственно логику работы программы, но который необходимо писать

                                int *p_scalar = new int(5);
                                — в большинстве случаев писать по два раза тип не необходимости (а некоторые до сих пор используют венгерскую нотацию и пишу его три раза).
                                  +1
                                  Тот факт, что в C++ много бойлерплейта (а в Java ещё больше) не отменяет того факта, что существуют языки со статической типизацией, где его мало: Haskell, OCaml, etc.
                                    +1

                                    Ну я же говорю, снова путают статическую типизацию и явные аннотации типов.


                                    % ghci
                                    GHCi, version 8.4.3: http://www.haskell.org/ghc/  :? for help
                                    Prelude> x = "meh"
                                    Prelude> :t x
                                    x :: [Char]

                                    Тип указан ровно ноль раз, а он есть.

                                      0

                                      C++: auto p_scalar = new int(5);
                                      Rust: let p_scalar = Box::new(5);
                                      Много бойлерплейта? И мало ли его будет, когда вы будете руками писать какую-нибудь сериализацию?

                                        0
                                        при живых serde.rs/derive.html и хаскельном deriving руками писать сериализацию как раз и не особо нужно
                                          0

                                          Я имел ввиду интерпретируемые языки, где ничего подобного нет.

                                            0
                                            В интерпретируемых код шаблонизаторами генерят, или вообще в рантайме.
                                +12
                                за удобство и фичи надо платить производительностью.

                                Лолшто?
                                Производительностью платят за дешевизну и скорость разработки.
                                Для создания высокопроизводительного приложения не требующее ресурсов надо нанять команду высококвалифицированных специалистов + опытных (и значит дорогих) тестировщиков + приложение скорее всего будет работать на какой-то одной платформе.
                                Понятно что бизнесу проще и дешевле работать с толпой безликих индусов используя бесплатные фреймворки и инструменты, предоставляющие кроссплатформенность из коробки.
                                Не понимаю причем тут удобство и features.
                                  +2

                                  Персистентные деревья отжирают память десятками мегабайт, имхо.

                                    +12
                                    Это конечно тоже частая причина падения производительности, тем не менее сложность не обманешь, вы можете хоть Кнута и Вирта посадить на разработку, но код быстрее деплоиться на удаленный сервер не будет и умножение у вас линейно не начнет происходить.
                                      +2
                                      тем не менее помимо сложности алгоритмо есть еще и внутренне устройство компьютера, которая может алгоритм сложность 0(N^2) выполнить быстрее чем O(N log(N)) за счет особенностей архитектуры и особенностей данных с которыми работает программист. Да и когда разработчики накручивают кучу абстракций поверх абстраций поверх абстракции поверх фреймфорков тоже играет свою роль.
                                        +1
                                        Зато эти абстракции работают, в отличии от кода который и под разными дистрами линукса не запустишь, не говоря уже о том чтоб он запускался на всех распространенных ОС.
                                          +2
                                          Хочу пример такого алгоритма и данных. Спасибо.
                                            +3
                                            О нотация показывает как растет функция т.е. показывает ассимптотическую сложность и при этом опускаются постоянные коэфициенты, как примеру — сортировка вставкой будет работать быстрее на маленьком количестве данных чем быстрая сортировка.
                                            www.quora.com/Why-is-an-insertion-sort-faster-than-Quicksort-in-little-arrays
                                            Плюс ко всему при сортировке вставкой данные намного лучше ложатся в кеш, за счет линейности.
                                              +1
                                              Спасибо, это я знал, думал что то более специфичное
                                                +2
                                                более специфичное это какое? Данный пример хорошо демонстрирует что нужно знать архитектуру компьютера и задача не всегда состоит в том, чтобы использовать существующий алгоритм, бывает нужно просто пробежаться по данным, и иногда выгоднее данные скопировать просто в линейный массив (к примеру из дерева) и потом в отдельной задаче пробежаться по нему и выполнить всю необходимую работу (на примере дерева — будет значительно быстрее чем выполнять эту же самую задачу в каждом узле), как пример подобной задачи — ray tracing, в один массив складываем простые структуры — запросы с нужными данными для вычисления, в другой массив складываем результат, при обходе сцены состваляем запросы, в конце линейно обходим данный массив, выполняем задачи рейтрейсинга и складываем результат своей работы в другой массив. Вот другие примеры: поиск в линейном массиве может быть быстрее чем поиск в heap-based BST дереве, log n бинарный поиск в отсортированном массиве может быть быстрее чем O(1) поиск в heap-based хеш табличах. Big-O нотация чаще выигрывает для больших значений n.
                                                Пример рейтресинга взят отсуюда: gamesfromwithin.com/data-oriented-design-now-and-in-the-future
                                                также может быть интересно: vimeo.com/97337258
                                                  0
                                                  Спасибо за подробный ответ и рейтресинг
                                      0
                                      Не объяснила. Потому что Atom написан на не особо быстром JavaScript, а нормальные редакторвы выполняют те же операции из этой, несомненно, интереснейшей статьи, используя более производительные языки и инструменты.
                                        –9
                                        IDEA написана на быстрой java, однако она некоторые операции делает куда медленнее nano и vim, однако мы массового упадка рынка IDE не наблюдаем.
                                          +8
                                          быстрой java
                                          Спасибо, поржал.
                                            0
                                            ?
                                              +1

                                              Эх, был у меня ИБП, и шла в комплекте к тому ИБП программуленька чтобы показывать пяток параметров и лесяток настроек. Была эта программуленька на Java и ЖРАЛА СО СТАРТА 1 ГИГАБАЙТ ПАМЯТИ!!!!!111

                                                0
                                                Возможно, стоило узнать про параметры -Xmx и -Xms?
                                                  0
                                                  Возможно, стоило узнать про параметры -Xmx и -Xms?

                                                  Мысль о том, что, возможно, стоило написать эту программуленьку на чём-то другом, Вам в голову не приходила?

                                                    0
                                                    Вы считаете, что талантливый индийский разработчик не сможет так написать эту программу на другом языке, чтобы она жрала 1 гб памяти?
                                                      +5
                                                      Да не вопрос!

                                                      static int a[1024*1024*1024/sizeof(int)];

                                                      (где-то на хабре была байка, что один опытный разработчик начинал все программы с похожей строчки, а когда начальство жаловались, что памяти не хватает и надо оптимизировать код, уменьшал в ней число ;)
                                                      0
                                                      Вам в голову не приходила мысль о том, что если указать 1 флаг, то программа будет работать так же, но потреблять будет на 995MiB меньше?
                                                      Ничего менять даже не нужно было бы, только указать флаг.
                                                      DGG говорит про 1GiB — какое-то время(много лет назад) это было стандартное значение флага Xms в windows.
                                                        0
                                                        если указать 1 флаг

                                                        Вы издеваетесь, или потомок того слесаря?


                                                        Откуда этот подход — "сделаем плохо, но если нажать кнопку, то станет хорошо"? Почему нельзя поставлять продукт с уже нажатой кнопкой?

                                                          0
                                                          Потому что кнопка — не часть продукта?
                                                            0
                                                            Простите, но кнопка — часть продукта, хоть и косвенно
                                                  +2
                                                  А зря смеётесь — подобный уровень IT-грамотности нынче распространён. Пристроил зад на кресло с зарплатой — значит специалист, не выгнали через пол года — значит хороший специалист, а если ещё и зп подняли — так вообще гений. Вот и все критерии, а не какая-то там производительность, оптимизация и т.д. Это ж думать надо, а «рынок думанья» в «массовом упадке».
                                                    +3
                                                    Люди, которые смеются на джавой и жалуются на то, что она жрет много памяти — отличное тому подтверждение. Не разбираются ни в оптимизации, ни в том, что же делает jit, ни в том, почему иногда нативный код на C++ оказывается медленнее, ни в том, почему же она ест так много памяти, зато смеяться над ней и хватить С++ — это они сразу.
                                                      +2
                                                      Понимаете — все ваши рассказы были бы хороши если бы вы после этого ещё и продемонстрировали быстро работающее приложение с малым потреблением памяти на Java. Но вот почему-то с бенчмарками у Java всё прекрасно, а вот с реальными приложениями — нет: жрут память, как не в себя, и тормозят не по детски.
                                                        0
                                                        Работаю в Eclipse с 1GB хипа, ничего не тормозит, выдаваемая память соответствует получаемому функционалу и его разнообразию.
                                                          +2
                                                          Это уже пошли «разговоры для бедных»: да, я вожу на дачу мешок картошки на 250-тонном Белазе, но это нормально, так как с него крутой обзор, а бензин у нас дешёвый.

                                                          Напомню, что, в своё время Emacs считался невероятно прожорливой программой и даже имел расшифровку Eight Megabytes And Constantly Swapping… а вы тут про 1GB хипа рассказываете как про нечто «малопотребляющее».

                                                          Притом что файлики-то в основном остались в тоже диапазоне: я мало где видел исходники больше, чем на 100-200K, с которыми даже TOR на Ямаха КУВТ справлялся.
                                                          0

                                                          А какие же это вы приложение сравниваете?
                                                          Вот у меня есть классный пример — ScyllaDB, которая как раз хочет выехать на таких людях, в маркетинговых заявлениях пишет "вот наша БД написана на C++, она в 10 (!) раз быстрее, чем эта ваша Cassandra на java" и даже графики приделала.


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


                                                          По каким приложениям вы делаете вывод, что java тормозит, по ide от jetbrains наверное? И сравнивания, разумеется, с QT creators, потому что никакой другой нормальной ide на c++ почему-то не написано.

                                                            +2
                                                            А какие же это вы приложение сравниваете?
                                                            Любые. Хотите — Vuze и uTorrent. Хотите — Visual Studio 6.0 и IntelliJ IDEA тех времён (начиная с Visual Studio 2005 IDE получает всё больше C# компонент и становится всё прожорливее, так что сравнение становится некорректным). Можно и библиотеки какие-нибудь сравнить.

                                                            Вот только оказывается, что если бенчмарк покрутить по другому, то scylla еще и медленнее оказывается.
                                                            А если пойти по ссылке? И почитать? То окажется, что ScyllaDB работает таки быстрее… если работает — но под большой нагрузкой рассыпается.

                                                            Ну так это, я извиняюсь, на 146% соответствует вы-всё-врёти «мифу» о том, что C++ требует меньше ресурсов, работает быстрее — но… требует более грамотных программистов.

                                                            Да, это известное достоинство Java: она порождает тормозных и глючащих монстров, плюющих исключениеми, на которые всем наплевать, в логи… но при этом вот эти вот монстры — работают, работают и работают… за что и любимы «суровым энтерпрайзом».

                                                            И сравнивания, разумеется, с QT creators, потому что никакой другой нормальной ide на c++ почему-то не написано.
                                                            Почему не написано? Написано. Было. А потом — да, сплыло. Когда приложение-монстр перерастает определённый размер и/или количество индусов в команде переходит определённую границу, то оказывается что приложение на C++ оказывается невозможно довести до релиза… ну так это другая история.

                                                            Я ж не говорю что нужно вот пойти, всё бросить и всё на свете переписать на C++.
                                                              0
                                                              Когда приложение-монстр перерастает определённый размер и/или количество индусов в команде переходит определённую границу, то оказывается что приложение на C++ оказывается невозможно довести до релиза

                                                              Ну, то есть программы на C++ быстрые, экономные и не жрут память. А ещё их нет. В общем-то я совершенно согласен.

                                                                +2
                                                                Ну, то есть программы на C++ быстрые, экономные и не жрут память. А ещё их нет. В общем-то я совершенно согласен.
                                                                Вы согласны с тем, что вы пользуетесь тем приложением, которого нет? Или вы этот комментарий пишете из секретного форка HotJava?

                                                                В том-то и дело, что приложений на C++ — выше крыши: это браузеры и игры, музыкальные и видеоплееры и многое, многое другое. Оно же бывает и на Java — и, в этом случае, тормозит и жрёт память вот это вот всё совершенно феерически. Когда программа с тремя кнопками жрёт память мегабайтами (а иногда и гигабайтами) — можно быть на 99% уверенным, что там внутри либо C#, либо Java

                                                                Но то, что определённый класс приложений написан, в основном, на C# и Java (хотя исторически сначала использовался Smalltalk) — ну, тому есть много причин… но дело уж никак не в том, что IDE на C++ написать нельзя.
                                                                  +1
                                                                  Когда программа с тремя кнопками жрёт память мегабайтами (а иногда и гигабайтами) — можно быть на 99% уверенным, что там внутри либо C#, либо Java

                                                                  Или javascript

                                                                    0
                                                                    я и на go и на C++ такие видел)
                                                                      +1
                                                                      Я — нет. Но про Electron я забыл, каюсь. Эта хрень, похоже, существует только для того, чтобы показать, что ресурсы можно тратить гораздо хуже, чем это делает Java, да…

                                                                      Просто программы на этом чуде работают настолько катострофически медленно и требуют такое чудовищное количество ресурсов, что у меня есть только одно такое: Steam client. Который, конечно, тратит ресурсов в 100 раз больше, чем такая программа должна бы… но альтернативы-то нету…
                                                                        0

                                                                        Кстати, у вас нет идей, где корень зла в веб-стеке?

                                                                          +2
                                                                          В том, что там очень много слоёв абстракции, которые призваны «упростить жизнь» неопытным разработчикам. Вот эти вот все CSS, фреймворки, транспилеры, полифиллы и прочее — они ведь далеко не бесплатны… и их много. Вот реально много.

                                                                          Причём большинство дизайнеров ведь особо не заморачиваются, когда их придумывают — всё происходит под флагом «преждевременная оптимизация — корень всех зол». Про оригинал, где говорится, на минуточку, «в развитой инжереной дисциплине улучшение в 12%, легко получаемое, никогда не рассматривается как несущественное — и я верю, что подобный же подход должен возобладать и в програмимровании» («in established engineering disciplines a 12 % improvement, easily obtained, is never considered marginal; and I believe the same viewpoint should prevail in software engineering») — все давно забыли.

                                                                          Какие 12%, о чём вы? Хорошо если очередная абстракция не увеличивает затраты вдвоё (потому что вызывает следующую абстракцию дважды без особой нужды), а всего лишь 15-20% замедления и/или потребления памяти добавляет!

                                                                          Ну а дальше — простая математика. Пусть «слоёв абстракции» у нас штук 15 и каждый вносить вроде-как-не-сильно-большую 15% неэффективность. И вот у нас уже 85%15 ≈ 8.7% уходит на решение хадачи, а 92.3% — тупо на нагревание окружающей среды.

                                                                          То есть какого-то большого криминала нет, просто есть катастрофически неээфективный дизайн. А дальше, когды вы такую башню выстроили… всё, приплыли. Пусть вы построили башню из 20 этажей и наняли «яйцеголовых», которые довели каждый из этих «этажэей» с эффективности в 30%-50% (как это было в MS IE 6) до, скажем, 90%. Какова итоговая эффективность? Правильно: 90%20 ≈ 12%.

                                                                          Слишком большое количество индирекций — это единственная проблема, которую нельзя решить введением ещё одного уровня индирекции… а по большому счёту это и есть проблема современного веб-стека!

                                                                          P.S. Чисто для сравнения: все иконки в GEOS имеют размер 24x21. Откуда такое странное число? А очень просто — они двуцветные и по горизонтали как раз ложится три байта. А всего под иконку нужно 64 байта (63 под биты и ещё целый байт на аттрибуты). Вот это — вполне себе решение в духе Кнута… и результат соответствующий. А как много решений в современном веб-стеке вы можете назвать, где бы учитывались бы реалии физического мира? Вот потому он он тормозит так и ресурсы так жрёт: он весь, снизу доверху, пропитан идеей «забудем о реализации, сделаем как „хорошо“… а потом уже — реализуем как-нибудь». Увы… это не работает. В лучшем случае вы получите того монстра, которого видите…

                                                                          P.P.S. И да: статья Кнута со словами про «преждевременную оптимизацию» и про «12%, которые не должны считаться несущественными» (и он прямо говорит о том, что технологии, которые не позволят ему выиграть эти самые 12% нужно отвегнуть «с порога») — это одна и та же статья. Разные её части, просто.
                                                                    –1
                                                                    Когда программа с тремя кнопками жрёт память мегабайтами

                                                                    Не судите по внешности) Каждая кнопка может «ракету в космос запускать».
                                                                      0
                                                                      То есть в драйверах, где управляющая панель была на MFC кнлпки какую-то фигню делали, а красивые кнопки на C#/Java «ракеты в космос запускают»? Но мне не нужны ракеты — мне б настроек парочку поменять…
                                                                        0
                                                                        Пёс его знает, что они там делают на самом деле, но вряд ли причина в C#/Java, если уж гигабайтами жрут формы с тремя кнопками.

                                                                        Да и должна же была быть какая-то причина переписывать то, что уже и так работает.
                                                                      0
                                                                      В том-то и дело, что приложений на C++ — выше крыши: это браузеры и игры, музыкальные и видеоплееры и многое, многое другое.

                                                                      Да, мне, похоже, стоило написать не приложения, а IDE. Я хотел сказать, что каких-то приложений на С++ просто нет, потому что их не написали. Это относится не только к IDE, а ещё и к львиной доле всяческого энтерпрайза.


                                                                      Рассуждения на тему того, что C++ быстрый, а Java медленная и жрёт память аналогичны рассуждениям, что Assembly language быстрый, а С++ медленный и жрёт память.


                                                                      То есть нередко программы на "более быстром" языке действительно быстрее, но аналогов софта, написанного на "медленном языке" у "быстрого языка" мало, если они вообще есть.

                                                                        +1
                                                                        Оно же бывает и на Java — и, в этом случае, тормозит и жрёт память вот это вот всё совершенно феерически.

                                                                        Кстати о птичках, интерпретатор Руби, написанный на Java (JRuby) существенно быстрее версии, написанной на Си (CRuby). Такие дела.

                                                                      +2
                                                                      Любые. Хотите — Vuze и uTorrent. Хотите — Visual Studio 6.0 и IntelliJ IDEA тех времён (начиная с Visual Studio 2005 IDE получает всё больше C# компонент и становится всё прожорливее, так что сравнение становится некорректным). Можно и библиотеки какие-нибудь сравнить.

                                                                      Visual Studio 6.0 вышла июнь 1998
                                                                      The first version of IntelliJ IDEA was released in January 2001

                                                                      Как вы будете это сравнивать то?


                                                                      А если пойти по ссылке? И почитать? То окажется, что ScyllaDB работает таки быстрее… если работает — но под большой нагрузкой рассыпается.

                                                                      Под большой нагрузкой она начинает проседать, выплевывать timeout, растет write latency и write throughput. Это называется тормозить, на мой взгляд.


                                                                      Ну так это, я извиняюсь, на 146% соответствует вы-всё-врёти «мифу» о том, что C++ требует меньше ресурсов, работает быстрее — но… требует более грамотных программистов.

                                                                      На мой взгляд все куда проще. Просто кто-то осилил локи и синхронизацию, что тормозят однопоточное приложение, зато дают буст в многопоточном, а кто-то просто фигашит записи исключительно в одном потоке. Это как говорить что Redis быстрый, потому что написан на C. Но секрет то не в этом.


                                                                      Почему не написано? Написано. Было. А потом — да, сплыло. Когда приложение-монстр перерастает определённый размер и/или количество индусов в команде переходит определённую границу, то оказывается что приложение на C++ оказывается невозможно довести до релиза… ну так это другая история.

                                                                      То есть приложение на C++ было бы быстрее, если бы его можно было написать. Классная реклама языка, ничего не скажешь :)

                                                                        +2
                                                                        Любые. Хотите — Vuze и uTorrent. Хотите — Visual Studio 6.0 и IntelliJ IDEA тех времён (начиная с Visual Studio 2005 IDE получает всё больше C# компонент и становится всё прожорливее, так что сравнение становится некорректным). Можно и библиотеки какие-нибудь сравнить.

                                                                        Visual Studio 6.0 вышла июнь 1998
                                                                        The first version of IntelliJ IDEA was released in January 2001
                                                                        Как вы будете это сравнивать то?
                                                                        А чём проблема? До 2002го года последней версий Visual Studio была именно 6.0, так что сранивать есть с чем.

                                                                        А если пойти по ссылке? И почитать? То окажется, что ScyllaDB работает таки быстрее… если работает — но под большой нагрузкой рассыпается.
                                                                        Под большой нагрузкой она начинает проседать, выплевывать timeout, растет write latency и write throughput. Это называется тормозить, на мой взгляд.
                                                                        Это называется — вы подсунули бензопиле железный лом. То, что в ScyllaDB ситуации жёсткого перегруза не предусмотрели — плохо. Но если вы обеспечиваете защиту от перегруза какими-то другими способами — то это для вас проблемой не будет.

                                                                        То есть приложение на C++ было бы быстрее, если бы его можно было написать.
                                                                        Нет. Оно уже было написано на C++. И было бы быстрее и сегодня если бы его не переписали с C++ на C#. Ктстати и сегодня Visual Studio быстрее, однако, во-первых разница куда меньше, а во-вторых сегодня это сравнение C# и Java, а не C++ и Java.
                                                                        Классная реклама языка, ничего не скажешь :)
                                                                        У чья бы корова молчала… Где ваша операционка на Java, браузер на Java и оффис на Java? Как они у вас — быстро бегают? Без Java программировать можно, а без C++ вы даже ваш саркатический комментарий на Хабре оставить бы не смогли.

                                                                        Вопрос почему некоторые продукты на Java выжили, а некоторые погибли и то же самое произошло с частью продуктов на C++ — можно долго обсуждать. Но вряд ли это можно привязать как-то к качеству языка — это скорее с маркетингом связано.

                                                                        Потому обсуждать можно, разумеется, только существующие продукты.
                                                                          0
                                                                          Вы говорите о программах написанных более чем 17 (!) лет назад. Я вас удивлю, но JVM и вообще виртуальные машины очень изменились с тех времен.
                                                                        0
                                                                        Такие приложения, как базы данных, работают с большим количеством данных и поэтому тут больше выигрывают разные хитрые алгоритмические решения, а вот для приложений, которые работают в рантайме на обычном железе, такие как игры, браузеры IDE итд, уже надо не только об эффективных алгоритмах думать (если конечно хочется повысить производительность). Как по мне в java одна фатальная проблема — это сплошные классы везде, нету value типов совсем (ну кроме самых примитивных типа int), что затрудняет работать с памятью эффективно, да и вообще выделить что-то не на куче, за счет этого и тормоза. И вся существующая экосистема вокруг java именно построена на классах с выделением на куче. Простенький пример: хочется мне рендерить интерфейс и у меня как обычно есть луп где постоянно вызывается какойнить progress и render, есть пара методов для отрисовки, в методе для отрисовке надо передать экземпляр класса Rect, к пример для указания определенных границ, и вместо того, чтобы это сделать value типом, т.е. структурой и просто выделить на стеке, передать и забыть, мы либо создаем экземпляр в лупе и имеем с этого кучу проблем, либо костылим. В новую java собираются добавить value типы, вот как добавят, вот заживем.
                                                                          0
                                                                          KDevelop на плюсах написан. А написанный на джаве clion почему-то понимает плюсы сильно хуже плюсатого clang'а.
                                                                            0
                                                                            Извините, я может не так понял, но вы только что сравнили IDE и компилятор.
                                                                              +1

                                                                              На самом деле я сравнил IDE и фронтенд, но не суть.


                                                                              В IDE для плюсов должен быть свой маленький компилятор (или интерпретатор) плюсов, потому что парсинг плюсов неразрешим, и для парсинга плюсов необходимо уметь выполнять constexpr-функции (а в C++03 нужно было тоже уметь выполнять пусть и чуть более уродливое, но тьюринг-полное подмножество языка).

                                                                        0
                                                                        А это тут при чём? Речь про то, что Java не для high performance, а для кросс-платформенности. И говорить о «быстрой java» значит не только не видеть ничего более производительного, но ещё и вообще не понимать ничего в том, что там под капотом. Т.е. херак-херак, тут костыль, там пару пакетов и в продакшн является нормой жизни и само собой разумеющимся, а не чем-то вынужденным из-за ограничений по срокам или ещё каких.

                                                                        И да, я не C/C++ разработчик, если что.
                                                                  +2
                                                                  JavaScript — язык без статической типизации, но при очень прямых руках на сегодняшний день его отставание в скорости от Си составляет 1\3. Гугл имел достаточно ресурсов для того, чтобы позвать его разрабатывать людей у которых опыт создания vm превышает 25 лет. Костяк разработчиков был взят из тех кто ранее занимался разработкой jvm.
                                                                  Конкуренция в скорости исполнения кода заставила двух других игроков (mozilla, microsoft) поднапрячься сильнее обычного и оптимизировать их движки.
                                                                  То что сайты тормозят и жрут немеряно памяти — следует не из того что js медленный, а из того что:
                                                                  1. Задача оптимизации при разработке виртуальных машин решалась относительно скорости исполнения. (но она решалась и решалась хорошо, потому этот пункт сам по себе не столь существенен)
                                                                  2. Каждый сайт — это отдельное приложение, если поставить миллионы программ, то 99% из них тоже будут кривыми и тормозящими (особенно если поручить разработку людям без алгоритмического бэкграунда)
                                                                  3. Для разработки действительно быстрых решений требуются настоящие специалисты, среднестатистический веб разработчик напишет код более низкого качества чем студент или школьник изучавший delphi\c#\java.
                                                                  4. Следствие пункта 4 — миллионы разработчиков сделали миллионы модулей (та самая экосистема языка). В случае с js экосистема получилась токсичной. Автор модуля решал свою задачу и выкладывал код в открытый доступ, его начинали использовать другие люди и в целом решение у них работало. За примерами далеко ходить не надо — достаточно в событие скролла окна несколько раз что-нибудь сделать с использованием популярнейшего jQuery (причём он не безнадёжно плох, если понимаешь сайдэффекты).
                                                                  5. Для написания действительно быстрых веб-приложений нужно знать O-нотацию, и устройство js-vm под капотом (понимания работы gc и реализации структур данных (массивов, объектов, классов и их расширения) достаточно).
                                                                    +1
                                                                    JavaScript — язык без статической типизации, но при очень прямых руках на сегодняшний день его отставание в скорости от Си составляет 1\3.
                                                                    Это на каких бенчмарках, интересно? Про реальный код не говорю — там отставание в разы.

                                                                    Для написания действительно быстрых веб-приложений нужно знать O-нотацию, и устройство js-vm под капотом (понимания работы gc и реализации структур данных (массивов, объектов, классов и их расширения) достаточно).
                                                                    Для написания действительно быстрых приложений нужно выкинуть JS нафиг, написать всё на C++ с отрисовкой на canvas и скомпилировать в wasm.

                                                                    Но после этого возникает вопрос: а нафига это всё? Если так напрягаться, то можно уж и нативное приложение сделать…
                                                                      0
                                                                      JavaScript — язык без статической типизации, но при очень прямых руках на сегодняшний день его отставание в скорости от Си составляет 1\3.

                                                                      Я что-то не думаю, что если я перепишу свой random forest с плюсов на JS, то он полмиллиона семплов по тыще фич каждый будет обрабатывать за 9 минут вместо 6 (а плюсокод у меня упирался в шину памяти).

                                                                    +2
                                                                    Там претензии предъявлялись редакторам несколько другого класса. Да и статья про приоритеты. И тут мы имеем хорошую иллюстрацию.

                                                                    Насколько я видел, идея занялась производительностью в последнюю очередь, когда фичи стало придумывать сложно. В 12 году, когда социальное давление таки заставило меня пересесть на неё, при печати регулярно повторялись фризы в пару секунд, на дополнениях до 20. Комфортными стал последний релиз 14го насколько я помню.
                                                                      +1
                                                                      Просто Идея начала всё выносить в фоновые потоки из UI-потока, когда многоядерные машины стали мейнстримом. До этого выхлопа от такого усложнения была заметно меньше. А так-то производительностью и раньше заморачивались, только новые фичи появлялись быстрее.
                                                                        –2
                                                                        А какое отношение многозадачность(concurrency) имеет ко многоядерности(parallelism)? Это перпендикулярные вещи.
                                                                          +3
                                                                          Отнюдь не перпендикулярные. Если вы из UI-потока скидываете фоновую активность в соседний поток, а потом единственное ядро должно вытеснить UI-поток, чтобы эту фоновую активность поисполнять, кто будет разгребать последующие UI-эвенты? Выгода от вытесняющей многозадачности на одном ядре существенно менее заметна, чем на многопроцессорной машине, поэтому тратить время разработчиков на разделение активностей по потокам в мире однопроцессорных машин неоправданно.

                                                                          И если уж придираться к словам, то многозадачность — это multitasking по-английски и не очень связана с нашим предметом обсуждения.
                                                                            0
                                                                            Вы продолжаете путать эти два понятия, которые к английскому языку не имеют опять же никакого отношения.

                                                                            parallelism — возможность выполнять несколько задач в одно и то же время (на разных ядрах).
                                                                            concurrency — возможность выполнять задачу, не дожидаясь завершения остальных (на любом числе ядер).

                                                                            Так вот, фоновые задачи — это про concurrency.
                                                                              0

                                                                              Под concurrency имеется в виду ситуация, когда несколько задач изменяют одну и ту же сущность. При этом, строго говоря, не обязательно, чтобы задачи работали одновременно, но в 99% случаев речь именно об этом.

                                                                                0

                                                                                Нет, concurrency — это способ модуляризации потоков выполнения, так сказать, с потенциально недетерминированным результатом.


                                                                                А то message passing у вас резко перестало быть конкурентным.

                                                                      0
                                                                      Помню в 2002 думал, что лет через 10 все программы будут летать и настанет утопия.
                                                                      2018 — утопии не настало, программы стали прожорливыми и не поворотливыми.

                                                                        0

                                                                        deleted

                                                                          –1
                                                                          И что за удобство и фичи надо платить производительностью.

                                                                          скажите это Notepad++.
                                                                          ПС. Я обойдусь без рефакторинга, но кодеджамп (прикрутил, кривовастенько правда, благодаря плагину jN), без него никак..

                                                                            +2
                                                                            Знаете я тоже поначалу писал чуть ли не в kate, теперь понимаю что программирование хоть маломальского проекта без любой IDE — это пожирание кактуса.

                                                                            После того как попробуешь инструменты автоматизации полностью пропадает желание делать это руками.
                                                                              0

                                                                              У каждого есть свои предпочтения. Я пристрастен к быстрым IDE и редакторам.
                                                                              Для C++/c я само собой выберу среду где есть умный рефакторинг, а вот для html, js, vbs, bat — Notepad++ с плагинами и с встроенным JavaScript — то что надо.
                                                                              Что я ценю в разработке:


                                                                              • Кодеджампинг.
                                                                                Он может обеспечиваться внешними утилитами, такими как ctags. Использовать его достаточно просто: запуск ctags с параметрами и парсинг выходного файла. Мои любимицы в кодеджампинге:
                                                                                — переход к определению переменной/функции/процедуры
                                                                                — переход к функции/процедуре с выбором.
                                                                                — переход к объекту пространства проекта.
                                                                              • Шаблонизатор: разворачивание текстового шаблона в конструкцию.
                                                                              • Оборачиватель: оборачивает текст в конструкцию по выбору.
                                                                              • Intellisense и автодополнение.
                                                                              • Хелп джампинг.
                                                                              • Форматирование: внешняя утилита tidy.exe
                                                                                Все это у меня в Notepad++ настроено плагинами и скриптами. Признаюсь, кривовато, но пока устраивает. Что не устраивает я просто иду и правлю скрипты (работающие с пом. плагина jn-npp-plugin ).
                                                                              • Кодеджампинг: Intell.js, funclist.js
                                                                              • Шаблонизатор: Intell.js, TemplaterF.js
                                                                              • Оборачиватель: trdmBrackets.js
                                                                              • Intellisense и автодополнение: Intell.js, intelOle.js, IntellUntil.js
                                                                              • Хелп джампинг: плагин Language Help by Franco Stellari
                                                                              • Форматирование: trdmTidy.js (зачатки)
                                                                                Репо проекта, не особо актуальная.
                                                                                Возможно будет интересна любителям N++, которые владеют js.
                                                                          +3
                                                                          А после того, как мы разметили текст, нужно ещё нарисовать его на экране. И вот тут тоже могут вылезать совершенно неожиданные грабли. Например: отрисовываем мы текст моноширинным шрифтом. Часть regular, часть bold, а часть italic. Естественно, хочется, чтобы буковки, вне зависимости от стиля, рисовались правильными колоночками, одна под другой. И вот тут внезапно выясняется, что ширина символов зависит от написания, и символы bold'ом будут шире, чем regular! Для моноширинного шрифта, ага. И приходится вставлять жуткие костыли, растягивая одни строки и сжимая другие, чтобы на экране всё было красиво и аккуратно. А ведь есть ещё дивный мир RTL языков (right-to-left — арабский, иврит и т.д.), которые тоже кто-то может захотеть использовать (хотя бы для комментариев).
                                                                            0
                                                                            Это не моноширинный шрифт тогда, увы. Хотя я как-то на заре юникода игрался с странными глифами в консоли и иногда получал длинные символы (до 3em), и это в моноширинной-то консоли!
                                                                              0
                                                                              Couriew New достаточно моноширинный?
                                                                              Заголовок спойлера
                                                                              #include <windows.h>
                                                                              
                                                                              const LPSTR text=TEXT("The quick brown fox jumps over the lazy dog");
                                                                              
                                                                              void main()
                                                                              {
                                                                                  HFONT reg=CreateFont(16,
                                                                                                       0,
                                                                                                       0,
                                                                                                       0,
                                                                                                       FW_NORMAL,
                                                                                                       FALSE,
                                                                                                       FALSE,
                                                                                                       FALSE,
                                                                                                       DEFAULT_CHARSET,
                                                                                                       OUT_TT_PRECIS,
                                                                                                       CLIP_DEFAULT_PRECIS,
                                                                                                       DEFAULT_QUALITY,
                                                                                                       DEFAULT_PITCH|FF_DONTCARE,
                                                                                                       TEXT("Courier New")
                                                                                                       );
                                                                                  HFONT bld=CreateFont(16,
                                                                                                       0,
                                                                                                       0,
                                                                                                       0,
                                                                                                       FW_BOLD,
                                                                                                       FALSE,
                                                                                                       FALSE,
                                                                                                       FALSE,
                                                                                                       DEFAULT_CHARSET,
                                                                                                       OUT_TT_PRECIS,
                                                                                                       CLIP_DEFAULT_PRECIS,
                                                                                                       DEFAULT_QUALITY,
                                                                                                       DEFAULT_PITCH|FF_DONTCARE,
                                                                                                       TEXT("Courier New")
                                                                                                       );
                                                                                  HDC dc=CreateCompatibleDC(GetDC(NULL));
                                                                                  SIZE sz;
                                                                                  SelectObject(dc, reg);
                                                                                  GetTextExtentPoint32(dc, text, wcslen(text), &sz);
                                                                                  printf("Regular: %d\n", sz.cx);
                                                                                  SelectObject(dc, bld);
                                                                                  GetTextExtentPoint32(dc, text, wcslen(text), &sz);
                                                                                  printf("Bold: %d\n", sz.cx);
                                                                              }
                                                                              


                                                                              Вывод:
                                                                              Regular: 176
                                                                              Bold: 154

                                                                              Только непонятно, почему bold у́же получился.
                                                                                +1
                                                                                А так:
                                                                                int main()
                                                                                {
                                                                                	HDC dc = CreateCompatibleDC(GetDC(NULL));
                                                                                
                                                                                	int nHeight = -MulDiv(16, GetDeviceCaps(dc, LOGPIXELSY), 72);
                                                                                
                                                                                	HFONT reg = CreateFont(nHeight,
                                                                                		0,
                                                                                		0,
                                                                                ...
                                                                                


                                                                                :-)
                                                                                  0
                                                                                  Интересно. Да, так получается одинаковая ширина при любых значениях высоты (до 32 как минимум). К сожалению, мне надо было задавать размер ячейки шрифта (для этого первый параметр должен быть положительным), а тут указывается размер символа. Но всё равно интересно, почему при размере шрифта 16 (по моему способу) и при 9 (по вашему, через MulDiv) шрифты получаются визуально одной высоты, но вот ширина у них разная.
                                                                              +1
                                                                              > Для моноширинного шрифта, ага.
                                                                              С чего бы это?
                                                                                0
                                                                                См. выше пример. Дефолтный моноширинный шрифт.
                                                                                  0
                                                                                  Как-то странно: «bold у́же». Как минимум должен быть не меньше :-)
                                                                                  Что-то здесь не так. Я не просто так встреваю в разговор. Глянул сейчас на своё поделие. Попробовал именно «Courier New» и всё в порядке. Не знаю, почему у вас так получается.
                                                                              0
                                                                              А чего xi не упоминаете? (да, они молодые, дерзкие, ничего ещё не умеют, но много обещают).
                                                                                +4
                                                                                Упоминается 4 раза.
                                                                                  +2
                                                                                  Посыпаю голову невнимательностью.
                                                                                  0

                                                                                  Блин, за месяц который раз встречаю его упоминание. Видимо пора подробнее почитать про него)

                                                                                    +2
                                                                                    Пользы от него мало, амбиций много. Всё, что я на базе xi щупал, ужасно сырое. Например, xi-gtk иногда просто падает. Xi-qt вообще может зависнуть в бесконечном цикле.

                                                                                    Хотя идея декларируется офигенная — разделение визуализации и, собственно, текстового движка.
                                                                                      0
                                                                                      Хотя идея декларируется офигенная — разделение визуализации и, собственно, текстового движка.

                                                                                      Такая же идея была у подзаброшенного открытого клона Sublime Text — https://github.com/limetext/lime

                                                                                        0
                                                                                        Я не смотрел во внутрь, но сама декларация «бэкэнд для lime» не звучит как универсальная библиотека для редакторов, и больше похоже на liblime, реализующую важные для lime вещи. (Я не знаю что внутри кода, но name matters).

                                                                                        А xi с самого начала заявлял editor agnostic.
                                                                                        0
                                                                                        Хотя идея декларируется офигенная — разделение визуализации и, собственно, текстового движка.

                                                                                        У NeoVim вроде бы тоже. Правда я после года использования NeoVim вернулся на обычный, так как мне как пользователю от такого разделения ни жарко ни холодно, а настроить копирование и вставку между nvim и другими приложениями, я так и не смог. Все время что-то либо не копировалось, либо не вставлялось.

                                                                                          0
                                                                                          Так в статье как раз не пользовательские вопросы и обсуждают.
                                                                                      +1

                                                                                      Как уже говорили — упоминают


                                                                                      Xi-Editor — это новый блестящий редактор от Google

                                                                                      Правда вот в репозитории чёрным по белому написано


                                                                                      This is not an official Google product (experimental or otherwise), it is just code that happens to be owned by Google.

                                                                                      Чувствую у Xi-editor отношения к Гуглу примерно столько же, сколько у встроенного постгреса для джавы к Яндексу

                                                                                      +9
                                                                                      Под капотом всё ещё только начинается, но буковка-то уже перед ним горит.

                                                                                      А потом через доли секунды рррраз и гаснет. А печатается в итоге в другом документе, который сейчас вообще закрыт.

                                                                                        +2
                                                                                        Именно. Дорогие разработчики Intellij, ну пожалуйста, сконцентрируйтесь уже, наконец, на качестве.
                                                                                          +1

                                                                                          Я две недели исправлял тонну инспекций, чтобы наличие и отсутствие скобочек в неожиданных местах не влияло на поведение. Как думаете, я достаточно сконцентрирован на качестве? :-)

                                                                                            0

                                                                                            Имеются в виду стабильность и лаги.
                                                                                            Кстати, у меня есть такая проблема:
                                                                                            Если в момент, когда CLion показывает список автодополнения переключиться на что-то другое, например браузер, то среда виснет. Если набрать какой-то текст в терминале, отвисает. GNOME.

                                                                                              +1
                                                                                              Баг-репорт в YouTrack завели? Логи, треддампы, снэпшоты приложили?
                                                                                                0

                                                                                                Написал в техподдержку (кстати, когда писать в багтрекер, а когда в ТП?).
                                                                                                https://intellij-support.jetbrains.com/hc/en-us/requests/1784220.

                                                                                                  +2
                                                                                                  Вопрос хороший. О багах я рекомендую писать прямо в YouTrack — оттуда короче путь к сердцу разработчика (в zendesk разрабы сами не смотрят, если саппорт не попросит). В zendesk лучше писать вопросы, а как сделать то-то. Ну ещё в YouTrack на русском как-то некрасиво писать, а в поддержку можно :-)
                                                                                          +2

                                                                                          Баг-репорт есть?

                                                                                            +2

                                                                                            Проявлялось на прошлом райдере после особой последовательности действий. Сейчас-то уже починено, но осадочек от "давайте обманем пользователя и нарисуем сразу" остался.

                                                                                          –1
                                                                                          Что это такое? Это когда один пользователь сидит в Индии, другой — в Японии, они пытаются в один и тот же Google Docs что-то напечатать и хотят какого-то предсказуемого результата.

                                                                                          Э… но у нас же есть git и другие системы контроля версий?
                                                                                          Непонятно как вообще без контроля диктатора можно прийти к какому-то вменяемому результату при конфликте слияния текста.
                                                                                            +2
                                                                                            Микроблокировки курсоров.

                                                                                            Т.е. у каждого в тексте свой курсор, и менять текст он может сколько угодно, но только если эти изменения не затрагивают чужой курсор.
                                                                                            +1
                                                                                            Больше интересно как документ хранится в памяти и как устроен хеш «проекта»? Какая сложность операции «Я кликнул мышкой посередине экрана с кодом»? Кеш же не кроссплатформный? Используете чанки памяти, выравненные структуры и прочие SIMD? Во что разворачивается в памяти? Suffixtrie/SuffixArray/InvertedIndex? Как индексируете текст? Что быстрее ищет? rgexp или просто текст? Какой максимальный размер чанка? 16TB? 16EB?
                                                                                              +1

                                                                                              Для текста триграммы используются. Насколько я понимаю (не уверен), если в регекспе есть кусок плейнтекста, он пробивается по триграммам, а дальше обычный джавовый движок. Если в регекспе нет подряд идущего куска плейнтекста из трёх символов, то перебираются все файлы проекта.

                                                                                              0
                                                                                              Текстовый редактор — это очень увлекательная штука при разработке. Если правильно декомпозировать всё, то все эти алгоритмы неплохо уживаются друг с другом. Главное тестами покрывать. Думаю, тестов будет примерно 80% от написанного кода.

                                                                                              А идея с присвоением каждому символу документа уникального идентификатора мне очень понравилась. По сути — первичный ключ, по которому можно организовать индекс для поиска: O(1) в виде массива, O(1)~O(log n) для хеша или на крайняк O(log n)~O(n) для дерева. Накладные расходы по сравнению с работой через смещения из-за с передачи на расстоянии несущественные.

                                                                                              Мало того, уникальные идентификаторы прекрасно вписываются в концепцию множественных указателей. В этом случае мы вставляем текст не в заданные позиции, а за символами с определёнными идентификаторами.

                                                                                              С уникальными идентификаторами все вышеописанные примитивные алгоритмы становятся намного интереснее. :) А ведь это всё ещё можно попытаться распараллелить…

                                                                                              А вообще, интересно, какой процент людей не заметил в статье животноводство?..
                                                                                                0
                                                                                                и текст на зеленом фоне ^^
                                                                                                +13
                                                                                                Теперь при лагах в текстовом редакторе я буду думать: «Понимаю, как тебе сложно! Я терпеливо подожду..»
                                                                                                  +3
                                                                                                  После «культ урологии» ожидал увидеть шутку про «мультиканальный».
                                                                                                    0
                                                                                                    Угу. Отмелькала.
                                                                                                    0
                                                                                                    NetBeans, Eclipse и Emacs используют Gap Buffer — молодцы! Vi не заморачивается и использует просто список строчек. Word использует Piece Table (недавно они выложили свои древние сорцы и там даже можно что-то понять).
                                                                                                    Чем просто список строк не устроил? Уж в плохой производительности vi точно не обвинить.
                                                                                                      +3
                                                                                                      При изменении длинны строк, типа увеличения шрифта или полей, при такой схеме документ надо по-сути пересоздавать заново. Vi со шрифтами не работает и WYSIWYG не обещает — ему можно.
                                                                                                        0

                                                                                                        И часто вы шрифт меняете когда печатаете?

                                                                                                          +10
                                                                                                          Разные размеры, стилевые выделение типа жирного или курсивного — часто.
                                                                                                          0
                                                                                                          Сама же строка не меняется, меняется только её отображение. Строчки все на экране одинаковой высоты, символы все одинаковой ширины, положение любой строки и любого символа на экране просто вычисляется, как y = (номер строки * высота строки) — позиция скролла. Зачем все эти сложности, из статьи непонятно, сложной разметки как в Word нет, стиль текста на ширину и высоту строки в моноширинном шрифте не влияет.
                                                                                                            +3

                                                                                                            Не всё так однозначно.


                                                                                                            Переносы строк (Word Wrap) могут растянуть одну физическую строку на несколько экранных.


                                                                                                            Code Folding, напротив, может схлопнуть несколько физических в одну. Да так, что в начале экранной строки будет первая физическая, в середине — сотая, а в конце и вовсе № 1024. И word wrap вишенкой на торте.


                                                                                                            Всё это при тотальной моноширинности.


                                                                                                            Вспоминаем, что у нас юникод, а это значит, что помимо честных печатных символов есть комбинирующие символы (символы ударения, grave, acute, ogonek и прочие над-, под- и сбоку- строчные символы). Ещё бывают пробелы нулевой ширины, эмодзи (куда же без них) и просто разлапистые китайские иероглифы, которые не очень дружат с моноширинностью.


                                                                                                            Ещё в редакторе IDEA есть parameter hints, которые могут менять ширину из-за изменений в другом файле (имя параметра в прилетевшем из Git-а файле изменилось, к примеру).


                                                                                                            «Просто вычислить» не так уж и просто получается.

                                                                                                              0
                                                                                                              Так в посте и про это и не говорится, Gap Buffer, Piece Table и т.п. для редактирования текста в памяти, рендеринга текста они не касаются.
                                                                                                              Для учёта свёрнутого текста и текста с переносами можно просто хранить их список или дерево, перед отрисокой строки проходим по нему и смещаем строку на размер блока — 1, вычисление смещения символа в немоноширинной строке тоже несложно.
                                                                                                                0

                                                                                                                Одно важное замечание: китайские, равно как и японские иероглифы, а также корейские буквы вовсе никакие не "разлапистые", они как раз всегда вписываются в квадрат. Причем этому вписыванию сотни лет. Откройте любую книжку, газету или сайт, испольюущий CJK: первое время в глазах будет рябить от квадратно-гнездового размещения символов. А ещё они пробелы между словами не используют.


                                                                                                                И ещё одно, уже не к вам лично, а просто куда-то в космос: как-то в народе прижилось абсолютно уродское слово "моноширинный" (чистая калька с "monospaced"), сотворённое горе-переводчиками, не знающими основ русского словообразования. А ведь есть замечательное, абсолютно уместное, активно используемое в других контекстах и вовсе не архаичное слово "равномерный"...

                                                                                                                  +1
                                                                                                                  А ведь есть замечательное, абсолютно уместное, активно используемое в других контекстах и вовсе не архаичное слово «равномерный»...
                                                                                                                  Оно, может, и замечательное — но типографы его не употребляют. Так что, увы, мокроступы ушли в прошлое…
                                                                                                                    0
                                                                                                                    Всё что угодно можно вписать в квадрат. Но если мы будем вписывать в квадрат одного и того же размера и китайские иероглифы и кириллицу с латиницей, то либо иероглифы превратятся в нечитаемое месиво, либо между буквами будут зиять расщелины. Либо придётся попрощаться с одинаковой шириной символов.
                                                                                                                0
                                                                                                                Я, может, глупый, но какая связь между шрифтом и данными — набираемым текстом?
                                                                                                              +5
                                                                                                              Xi-Editor — это новый блестящий редактор от Google
                                                                                                              Пожалуйста, исправьте. Не от Google, а от Рафа Левиена, который, к слову, около месяца назад из Гугла ушел.
                                                                                                                +1
                                                                                                                Поправили, спасибо
                                                                                                                0
                                                                                                                Всегда было интересно почему переключение раскладок не связано с текстовым буфером. Набираешь себе текст переключил раскладку и набираешь дальше и оказывается что первые несколько букв на старой раскладке набрались. Поэтому приходится после переключения делать паузу. Это наверное потому что 24 ядра и переключение раскладки теряется в этих соснах? И почему на клавиатуре есть символы почта, браузер, громкость, калькулятор и т.п. но нет кнопки РУС/ЛАТ. И всегда радовала глаз кнопка SysRq и ScrLock.

                                                                                                                По поводу текстовых редакторов. Помимо plain text файлов есть еще так называемые rich-text файлы раньше был rtf, wri, doc в линухах troff/groff и tex теперь все скатились на html и xml-и типа docx, odt, epub…
                                                                                                                А вот нормального широко распространенного форматированного текстового формата так и не появилось.
                                                                                                                Кроме pdf который предназначен только для просмотра и печати.
                                                                                                                Поэтому все кому не лень пытаются использовать разнообразные вариаций markdown-а. Но с реализацией никто не заморачивается md->html и смотрим браузером.
                                                                                                                  0
                                                                                                                  Набираешь себе текст переключил раскладку и набираешь дальше и оказывается что первые несколько букв на старой раскладке набрались. Поэтому приходится после переключения делать паузу.
                                                                                                                  Ну это вроде только в линуксах так.
                                                                                                                    0
                                                                                                                    Нет, в Windows то же самое, просто не так заметно, потому что у приложения, окно которого имеет фокус ввода, поднимается приоритет.
                                                                                                                      0
                                                                                                                      Просто текст с клавиатуры попадает сначала в буфер, а переключение раскладки путешествует другим путём, т.к. нет символа переключить раскладку. И это не только в linux но и в windows и mac
                                                                                                                      0
                                                                                                                      Ни разу с таким не сталкивался. По ощущениям — раскладка в Windows переключается мгновенно (особенно чувствуется, когда на одну кнопку, напр., CapsLock, настроено).
                                                                                                                      А если дело в только приоритете, то, может, давно пора пример с хорошего решения взять?
                                                                                                                        0
                                                                                                                        Запустите программу потяжелее, чтобы всё ушло в своп, начните копировать файл на флешку, чтобы загрузить систему — и столкнётесь. Я так добивался в Windows XP пару сотен часов… оказывается там банально при запуске процесса ищется окошко по имени и активируется, а если система загружена — то можно запустить несколько сотен процессов CLOCK.EXE пока первый из них своё окошко отрисует… хотя не факт, что этот эксперимент удастся повторить на SSD, я этот эффект регулярно наблюдал только на старых системах с HDD…

                                                                                                                        P.S. Хотя можно же Windows To Go использовать! Там, если ставить на несертифицированный стик, открытие окна или переключение раскладки секунд по 10-15 занимает…
                                                                                                                          0
                                                                                                                          Запустите программу потяжелее, чтобы всё ушло в своп, начните копировать файл на флешку, чтобы загрузить систему — и столкнётесь.
                                                                                                                          «— Доктор, мне больно, когда я делаю так. — Не делайте так.»
                                                                                                                          Мы точно про нормальные условия работы говорим?
                                                                                                                          Впрочем, у меня и на дохлом одноядернике, который реально в своп часто уходил, ни разу раскладка не ошибалась.
                                                                                                                        +1

                                                                                                                        До сих пор скучаю по Windows NT, где событие переключения раскладки синхронно отрабатывалось с остальными нажатиями и такой проблемы не было никогда, даже если всё сильно тормозило. В Windows 2000 всё сломали, теперь страдаем.

                                                                                                                      +2
                                                                                                                      И почему на клавиатуре есть символы почта, браузер, громкость, калькулятор и т.п. но нет кнопки РУС/ЛАТ.
                                                                                                                      Потому что подавляющее большинство разработчиков эти проблемы не волнуют. Они живут либо на Запада, где раскладка ровно одна и никто её во время переключения текста менять и не думает, либо на Востоке, где раскладка включает в себя множество подраскладок — и потому, собственно, также не переключается.

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

                                                                                                                        Справедливости ради, про какой Запад вы говорите? Англоязычный? Но есть раскладка QWERTZ для немецкоязычных пользователей, на которой есть специфичные для немецкого (как противопоставление английскому) языка символы ä, ö, ü и ß. AZERTY для франкоязычных пользователей...


                                                                                                                        Так что переключение РУС/ЛАТ не имеет смысла на Западе не потому, что у них одна раскладка, а потому что их раскладка не подпадает под категорию "РУС". Это уже не говоря о том, что не только "русская" раскладка использует кириллицу.

                                                                                                                          +1
                                                                                                                          РУС/ЛАТ
                                                                                                                          А Капс-Лок вам на что?
                                                                                                                            0

                                                                                                                            Мне? Я так понял, автора оригинального комментария смущает то, что для переключения раскладки используются неочевидные сочетания, а не тумблер РУС/ЛАТ.

                                                                                                                              0
                                                                                                                              На многих компьютерах, разработанных в России, даже если производились они за рубежом (как Ямаха КУВТ) был отдельный переключатель. Сейчас его нет, так как делать отдельную модель для не очень ёмкого (в мировых масштабах) рынка никто не будет.
                                                                                                                            0
                                                                                                                            Так что переключение РУС/ЛАТ не имеет смысла на Западе не потому, что у них одна раскладка
                                                                                                                            Я возможно несколько неаккуратно высказался. Да, раскладок и на Западе и на Востоке много. Но на компьютере немца будет QWERTZ, у француза AZERTY, а у японца — японская раскладка (построенная вокруг QWERTY) и, главное, у каждого из них будет одна раскладка (хотя в разных странах — разная).

                                                                                                                            Это уже не говоря о том, что не только «русская» раскладка использует кириллицу.
                                                                                                                            Страны СНГ, Болгария, Греция и, внезапно, Израиль — вот, по большому счёту, все страны, которых касается описанная вама проблема…
                                                                                                                              –2
                                                                                                                              и, главное, у каждого из них будет одна раскладка (хотя в разных странах — разная)

                                                                                                                              Так одна или разная? И что вы понимаете под одной раскладкой?


                                                                                                                              Страны СНГ, Болгария, Греция и, внезапно, Израиль — вот, по большому счёту, все страны, которых касается описанная вама проблема…

                                                                                                                              Я никакой проблемы не описывал, я пытаюсь понять, что вас не устраивает в текущем положении вещей, что


                                                                                                                              Арабам, грекам, и русским приходится «есть что дают»…
                                                                                                                                +2
                                                                                                                                Извините, наш разговор стал абсолютно бессмысленным. Все ответы на все ваши вопросы были описаны в начале треда.

                                                                                                                                Всли вашего внимания не хватает на то, чтобы три реплики прочитать — то непонятно о чём нам тут спорить.
                                                                                                                          0
                                                                                                                          И почему на клавиатуре… нет кнопки РУС/ЛАТ

                                                                                                                          Потому что в этом вопросе, как и в куче других, пользователи не договорились.Ваш покорный, к примеру, любит детерминизм, и не хочет помнить, РУС там сейчас или ЛАТ. Глаза косить в сторону на индикатор тоже не хочет.

                                                                                                                          А хочет брякнуть в кнопку РУС (правый шифт в моём случае), и строчить в чатике. А потом брякнуть в ЛАТ (левый шифт) и печатать в IDEшечке. И быть уверенным в том, что наберётся именно нужное — особенно актуально в свете дискуссий про тормоза.
                                                                                                                          +4

                                                                                                                          Текстовые редакторы — это весело. Да-да. И то что в статье затронуто — это только начало начал. На эти структуры надо еще накинуть "веселье" полноценной поддержки unicode, right-to-left, cr/cr+lf (помню как одному редактору срывало крышу от манипуляций с документом с ошибочно вставленными им же cr+cr+lf). Теперь добавляем конечные автоматы для расцветки и разбора, теперь в фоне начинаем дёргать PSI/корёжить AST (и рисовать имена параметров в месте вызова, например).


                                                                                                                          Кстати, решил проверить и наткнулся на забавный эффект в IDEA

                                                                                                                          Код на Kotlin


                                                                                                                          data class aleph (val אאאאאא:Int = 1)
                                                                                                                          data class alpha (val αααααα:Int = 1)
                                                                                                                          
                                                                                                                          fun main(args: Array<String>) {
                                                                                                                          
                                                                                                                              println(aleph())
                                                                                                                              println(alpha())
                                                                                                                          
                                                                                                                          }

                                                                                                                          Вывод (обратите внимание с какой стороны значение):


                                                                                                                          aleph(אאאאאא=1)
                                                                                                                          alpha(αααααα=1)
                                                                                                                            0

                                                                                                                            А что вас смущает?

                                                                                                                              0

                                                                                                                              Меня смущает, что я не понимаю почему =1 в разных случаях в разные стороны. И если немного усложнить пример, то я вообще не понимаю что и как.


                                                                                                                              Вот, например, объясните мне вывод в классе both
                                                                                                                              data class aleph1 (val אאאאאא:String = "йцу")
                                                                                                                              data class aleph2 (val אאאאאא:Int = 123)
                                                                                                                              data class alpha (val αααααα:Int = 123)
                                                                                                                              data class both (val αααααα:Int = 123, val אאאאא:Int = 123, val אאאאאא:String = "йцу")
                                                                                                                              
                                                                                                                              fun main(args: Array<String>) {
                                                                                                                              
                                                                                                                                  println(aleph1())
                                                                                                                                  println(aleph2())
                                                                                                                                  println(alpha())
                                                                                                                                  println(both())
                                                                                                                              
                                                                                                                              }

                                                                                                                              Вывод:


                                                                                                                              aleph1(אאאאאא=йцу)
                                                                                                                              aleph2(אאאאאא=123)
                                                                                                                              alpha(αααααα=123)
                                                                                                                              both(αααααα=123, אאאאא=123, אאאאאא=йцу)
                                                                                                                              
                                                                                                                                +2
                                                                                                                                Но ведь в TR9 всё описано! Есть три основных класса символов: которые читаются слава направо и которые читаются справа налево. А есть ещё и разворачивающиеся.

                                                                                                                                То есть если написать a > a, а потом заменить «a» на "א" — то знак больше станет выглядеть как знак меньше — попробуйте: א > א.

                                                                                                                                Если вы скопируете ваш «странный» вывод в консоль (ну или в GVIM/VIM, которому на TR9 наплевать), то никакого переключения направления вывода не будет и сразу станет понятно, что IDEA просто корректно реализует разработанный 20 лет назад алгоритм… и что в этом такого странного и страшного???
                                                                                                                                  0
                                                                                                                                  Ну если с первым примером всё более-менее понятно, но пример `both` меня совсем удивляет.
                                                                                                                                  Я не считаю это ошибкой, скорее демонстрацией мест, где достаточно сложно сориентироваться в «обычном тексте».
                                                                                                                                    +1
                                                                                                                                    В нём достаточно просто сориентироваться если скопировать текст в строку редактирования и попробовать выделять куска текста с помощью «Shift-влево» и «Shift-вправо». Они выделяют «непрерыную последовательность глифов», которая оказывается вот нифига не непрерывной если смешивается письмо «слева направа» и «справа налево». А все проблемы у вас с «both» потому, что вы переменные одинаково назвали.

                                                                                                                                    data class both (val αααααα:Int = 123, val אאטטט:Int = 123, val ממפפפ:String = "йцу")
                                                                                                                                    both(αααααα=123, אאטטט=123, ממפפפ=йцу)
                                                                                                                                    
                                                                                                                                    Вот тут — всё сразу можно понять: после вывода «αααααα=123» настала пора выводить «אאטטט=123» — что и было проделано. Справа налево, так как именно так принято у евреев… но числа они пишут как и мы, так что число не развёрнуто. Дальше пришла пора выводить «ממפפפ=йцу»… которое начали выводить «по еврейски»… но обнаружили русские буквы, которые означают, что часть "=йцу" нужно вывести по русски… она и вывелась — после еврейского блока «אאטטט=123, ממפפפ». Всё просто и понятно.

                                                                                                                                    Можно было бы перед запятой поствить LTR, что всё сразу же сделало бы куда менее загадочным: "αααααα=123‎, אאטטט=123‎, ממפפפ=йцу" — он, собственно, для этого и предназначен.
                                                                                                                                      0
                                                                                                                                      Пойду спрячусь обратно в простой и тупой хайлоадный бэкенд :)
                                                                                                                                        0
                                                                                                                                        Нашли где простоту искать. Там проблем гораздо больше, чем с LTR-алгоритмами и переносами строк… просто они — другие.