удалить и заменить текст при вводе строки в консоль $ stdin ruby - PullRequest
0 голосов
/ 03 октября 2019

У меня есть программа, которая является клиентом и обращается к серверу с socket.

Когда пользователь вводит сообщение, если приходит другое сообщение, оно визуально разбивает текст, делая еготрудно понять для пользователя.

сценарий можно придумать так:

c=0
p=Thread.new do
    loop {
        # this is the messages coming in
        c+=1
        puts c
        sleep 1
    }
end
g=Thread.new do
    loop {
      #this is the user input
      puts $stdin.gets  
    }
end
p.join
g.join

в случае некоторых очень медленных печатных машин результат выглядел примерно так:

1
h2
el3
l4
o5

hello

6

Есть ли способ удалить и заменить текст при вводе строки в консоль?

edit

Итак, теперь, если я могу получить каждый символ отдельно, я могудобавьте его в строку, и в потоке p, когда он будет помещен, он поместит "\r" + c, а затем напечатает строку.

, что позволит пользователю также видеть, что он печатает. не прерывая поток p.

Я не знаю, как получить каждый символ по отдельности.

это также поднимает проблему "как будет работать backspace?"и "мне нужен оператор switch для специальных символов, таких как return и ctrl + c?"

Ответы [ 2 ]

0 голосов
/ 03 октября 2019

Если вы пытаетесь внедрить приложение чата в терминале, «подходящим» инструментом будет curses . Библиотека curses, по сути, позволяет вам написать GUI в терминале. Он позволяет вам определять отдельные области экрана, которые вы можете обновлять отдельно, а также позволяет читать ввод, не передавая его на терминал.

0 голосов
/ 03 октября 2019

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

. Идея проста: всякий раз, когда поток взаимодействует с общим ресурсом (терминалом), синхронизирует этот доступ собщий мьютекс. Таким образом, они не давят друг на друга.

Но ваша ситуация хитрая, легко увидеть, когда поток p хочет использовать терминал, но это нелегко в потоке g, потому что это простопользователь печатает. Вероятно, вам придется использовать IO # read_nonblock в тесном цикле, чтобы получить вводимые пользователем символы за символом. Затем вы можете использовать это, чтобы определить, когда пользователь приостанавливает свой ввод, и использовать этот момент, чтобы разблокировать мьютекс, позволяя другому потоку выводить свой вывод.

Обратите внимание, что это также сделает поток p более сложным, посколькуон должен иметь возможность буферизовать свой вывод, пока он ожидает, пока терминал станет доступным.

...