Створіть простий редактор рядків


19

В: рядок без розривів рядків *
Дозволити користувачеві редагувати та надсилати рядок
Вихід: модифікована рядок (необов'язково із заднім рядком)

Редактор рядків повинен як мінімум дозволяти користувачеві:

  1. перемістити видимий курсор вліво і вправо

  2. вставити та / або перезаписати символи на позиції курсору

  3. видалити символи в позиції курсору

  4. подати новий рядок, тобто припинити редагування, тому що змінений рядок буде повернутий / надрукований / відображений / збережений… (без іншого тексту)

Оцінено, але не потрібно:

  • пояснення вашого коду.

  • посилання на веб-сайт для тестування, який може продемонструвати вашу програму / функцію

  • анімоване зображення, що демонструє використання (TIO, наприклад, не дозволяє взаємодія)

Примітка:

  • прив'язки клавіш - лише пропозиції

  • GUI або візуальний стиль не потрібно

Приклади

Далі курсор зображено с _.

В: Just some text
Дозволити користувачеві редагувати:
Just some text_  Користувач натискає (ліва клавіша зі стрілкою) дев'ять разів
Just ̲some text  Користувач натискає Delчотири рази
Just ̲ text  Користувач натискає  Користувач натискає :any
Just any_text Enter
Just any text

В: Remove me
Дозволити користувачеві редагувати:
Remove me_  Користувач натискає Backspaceдев'ять разів
_  Користувач натискає : (порожній рядок)Enter
 


* Щоб запобігти тривіальним рішенням редактора, це повинно або надаватися за допомогою іншого способу введення, ніж команди редагування, або бути відокремленим від них новим рядком або подібним.


Чи потрібно використовувати ці точні натискання клавіш для вводу / виводу? Також чи можемо ми створити файл для збереження тексту?
Rɪᴋᴇʀ

1
Прив'язки клавіш @Riker - лише пропозиції . Методи введення та виведення відповідають за замовчуванням PPCG .
Адам

Чи може рядок містити нові рядки? І чи можна використовувати новий рядок для "подання"?
Conor O'Brien

@ ConorO'Brien Ні; Простий редактор рядків . Так; Редактор повинен як мінімум дозволити користувачеві: (...) 4. подати новий рядок
Adám

1
Було б добре, якби ви вказали рядок у фактичному складі питання, оскільки заголовки на цьому веб-сайті не є точно специфікаціями ...
Conor O'Brien

Відповіді:


3

APL (Dyalog) , 5 байт

⍞←⍞⋄⍞

Це tradfn, тому, щоб його використовувати, зробіть

a
⍞←⍞⋄⍞

А потім зателефонуйте, використовуючи a, після чого ви подаєте початковий рядок, а потім зможете редагувати рядок.


8

JavaScript (ES6), 15 14 байт

Я не розумію, чому це отримує так багато відгуків!

s=>prompt(s,s)

Збережено байт завдяки пропозиції Адама , щоб я відображав оригінальний вхід у prompt.


Спробуй це

f=
s=>prompt(s,s)
console.log(f("Edit this ..."))


1
Зберегти байт, замінюючи ""з 0або навіть s(так що користувач все ще може побачити оригінальний текст , а редагування - акуратний функція).
Adám

5

Bash 4.x, 25 символів

read -ei "$*" t
echo "$t"

Проба зразка:

bash-4.3$ bash interactive.sh hello world
hello golfing world
hello golfing world

(У другому рядку вище було інтерактивне редагування, у рядку 3 - результат результату тексту.)


1
Не працює для мене -bash: read: -i: invalid option? manкаже ers, що дозволені лише прапори.
Rɪᴋᴇʀ

Так, я збирався запитати про це-ei
Adám,

-iбула введена в Bash 4.0 (випущена в лютому 2009 року) - "-i текст Використовуйте ТЕКСТ як початковий текст для Readline".
манатура

Цікаво, чи працювала б кішка?
Меттью Рох

catпросто чекає на вхідний потік, для якого оболонка не надасть функцій редагування. Принаймні, не за замовчуванням.
манастирство

3

Bash + Vi / Vim, 14 байт

echo $1>a;vi a

viє псевдонімом vimна MacOS, я не знаю про інших операційних системах.


Можливо, мені щось не вистачає, але чи відповідає це вимозі вивести змінений рядок?
Грейсон Кент

1
@GraysonKent ви можете зберегти та вийти, натиснувши :wq!або :x, тому я так думаю. ОП трохи незрозуміло, що кваліфікується як це.
Rɪᴋᴇʀ

3

HTML + JavaScript (ES6), 77 66 64 байт

HTML

<input id=t

JavaScript

onkeyup=e=>e.which-13||alert(t.value);f=a=>t.value=a;

Збережено 10 байт завдяки Йоргу Гюльсерману та 2 байти завдяки Луці.

onkeyup=e=>e.which-13||alert(t.value);f=a=>t.value=a;

f("Remove Me");
<input id=t>


2
ви можете видалити тип attribut для вхідного елемента
Jörg Hülsermann

Напевно, ви повинні використовувати oninputзамість цього.
Меттью Ро

@SIGSEGV Я не думаю, що oninputпожежі коли Enterнатискаються
Том

1
e.which==13?alert(t.value):0-> e.which-13||alert(t.value)зберігає два байти.
Лука

3

Python 2 , 275 200 байт

Не переможець, але ось:

from msvcrt import*
s=list(input())[::-1]
c=i=0
def p(a):print''.join(a)[::-1]
while'\r'!=c:p(s[:i]+['<']+s[i:]);c=getch();x=c!='\b';exec["s[i:i+1-x]=c*x","i=(i-1+2*(c<'\\t'))%-~len(s)"][x*' '>c]
p(s)

Пояснення:

Він працює, обертаючи вхід (з [::-1]), виключаючи та вставляючи символи в цей перевернутий вхід, щоб курсор не мав рухатися. Знову повертається під час друку.

Використання:

[Tab] для переміщення вправо
[Ctrl + C] для переміщення вліво
[Backspace] для видалення
[Return] для завершення редагування
Будь-яка інша клавіша буде вставлена ​​в текст

Приклад:

На прикладі ОП

В: Just some text
Just some text>
Just some> text  Користувач натискає Ctrl+Cп'ять разів
Just > text  Користувач натискає Backspaceчотири рази
Just any> text  Користувач натискає  Користувач натискає :any
Just any> text Enter
Just any text

Вбудована версія редактора:

Якщо ви хочете, щоб текст редагувався вбудованим, додайте ,'\r',в кінці printзаяви:

def p(a):print''.join(a)[::-1],'\r',

6
+1 Дуже приємно. Перша відповідь, яка насправді реалізує справжній редактор, на відміну від того, щоб покладатися на раніше існуючий функціонал. Я розглядав можливість подати ще один виклик, щоб зробити саме це.
Adám

Ви не можете зберегти байти, використовуючи інші клавіші ліворуч і праворуч?
Адам

Я міг би вважати персонажів як -і +робити це, але редактор не міг би тоді прийняти цих персонажів
Феліпе Нарді Батіста

Як щодо \tі \v?
Адам

1
Це проблема користувача, ні? Control + K, можливо?
Адам

3

C + NCURSES, 573 байт

#include <curses.h>
i;j;k;s;c;p;int main(a,b)char**b;{char*q;char t[999];if(a&&(q=b[1]))while(*q)t[s++]=*q++;i=s;initscr();noecho();keypad(stdscr,1);do{for(j=0;j<i;j++)addch(t[j]);addch('|');for(j=i;t[j];j++)addch(t[j]);c=getch();switch(c){case KEY_LEFT:if(i)i--;break;case KEY_RIGHT:if(i<s)i++;break;case 8:case 127:case KEY_BACKSPACE:if(i){for(k=i-1;k<s;k++)t[k]=t[k+1];i--;s--;}break;case KEY_DC:if(i<s){for(k=i;k<s;k++)t[k]=t[k+1];s--;}break;default:if(c>31&c<127){for(k=s;k>i;k--)t[k]=t[k-1];t[i]=c;i++;s++;}}clear();}while(c!=10);printw(t);getch();endwin();return 0;}

Тест

  • Компілювати та запустити із введенням Just some text.

введіть тут опис зображення

введіть тут опис зображення

  • Натисніть кнопку зі стрілкою вліво дев'ять разів.

введіть тут опис зображення

  • Натисніть кнопку Видалити чотири рази.

введіть тут опис зображення

  • Натисніть, aа nпотім y.

введіть тут опис зображення

  • Натисніть, Enterщоб припинити.

введіть тут опис зображення

Детально

#include <curses.h>

int main(int argc, char ** argv)
{
    char*q = 0;
    char t[999] = {0};
    int j = 0, k = 0;
    int i = 0; // cursor before first char
    int s = 0; // current size
    int c = 0; // current input
    int p = 0;

    // copy first command-line argument
    if(argc>0 && (q=argv[1]))while(*q)t[s++]=*q++; i=s;

    initscr(); // initiate NCURSES
    noecho(); // input does not echo on entry
    keypad(stdscr,TRUE); // handle all input

    do
    {
        // print current content with cursor
        for(j=0;j<i;j++) addch(t[j]);
        addch('|'); for(j=i;t[j];j++) addch(t[j]);

//      printw("\n\n> key %d pressed",c); // debug

        c = getch(); // read next char

        switch(c)
        {
            case KEY_LEFT: // left arrow; cursor left
            if(i > 0) i--;
            break;

            case KEY_RIGHT: // right arrow; cursor right
            if(i < s) i++;
            break;

            case 8: // backspace; remove previous char
            case 127:
            case KEY_BACKSPACE:
            if(i > 0)
            {
                for(k=i-1; k<s; k++) t[k]=t[k+1];
                i--;s--;
            }
            break;

            case KEY_DC: // delete; remove next char
            if(i < s)
            {
                for(k=i; k<s; k++) t[k]=t[k+1];
                s--;
            }
            break;

            default: // none of the above

            if(c > 31 && c < 127) // printable char
            {
                for(k=s; k>i; k--) t[k]=t[k-1];
                t[i] = c;i++;s++;
            }
        }

        clear(); // clear screen
        if(c == 10) break;
    }
    while(c);

    addch('\n');
    printw(t); // print final result
    getch(); // wait for any input
    endwin();
    return 0;
}

Ви не можете замінити KEY_*цілі числа, щоб зберегти кілька байт?
Серхіол


2

C #, 53 байти

s=>{SendKeys.SendWait(s);return Console.ReadLine();};

Де sслід змінити рядок, а вихід - нове значення.

SendKeys.SendWait : надсилає задані ключі активній програмі, а потім чекає, коли повідомлення будуть оброблені.

або 74 байти, якщо ми не в контексті Windows Forms:

s=>{System.Windows.Forms.SendKeys.SendWait(s);return Console.ReadLine();};

gif демо


2

Рубі, 9 19 22 84 байт

->s{r=Readline;r.pre_input_hook=->{r.insert_text s;r.redisplay};r.readline}

Це створює гачок попереднього введення Readline, який вставляє текст s і потім повторно відображає. Після цього irb заплутається, тому переконайтеся, що запустити це з файлу. Запускається як лямбда, він приймає рядок введення як аргумент і повертає вихідний рядок.

puts Readline.readline

При цьому використовується бібліотека Readline для редагування рядків. Моя попередня відповідь дозволяла лише зворотні простори.

puts gets

Це дійсно, справді само собою пояснюється.

Редагувати: мене попросили пояснити. Це еквівалентно puts(gets). getsвводить рядок за допомогою редактора рядків. putsвиводить його.


Ланцюг викликів методу: r.insert_text(s).redisplayта видаліть наступне ;. До речі, як я розумію нашу політику, ви повинні згадати, що ваш код працює irb, бо в іншому випадку вам потрібно буде вимагати Readlineу своєму коді.
манатура

1

PHP + HTML, 26 байт

<input value=<?=$_GET[0]?>

Браузер автоматично додає тег, що закривається

$ _GET Використання URL-адреси, такої як http://example.com?0=inputвведення створюється в HTML<input value=input

І це вихід для рядкового вводу

<input value=input


Чи слід вважати, що це працює? Можливо, ви можете додати пояснення, посилання чи анімацію?
Адам

@ Adám Так, ви можете припустити це, можливо, ви вдосконалите і встановите атрибут, autofocusщоб в ньому був курсор на початку. Інші елементи HTML, які ви також можете редагувати, якщо встановити атрибутcontenteditable
Jörg Hülsermann,

Вхід =test></input><script>alert("Hi");//some malicious code\n</script>
Роман Греф

@ RomanGräf Bad Boy. Так, краще відфільтрувати Javascript
Jörg Hülsermann

1

Tcl, 17

puts [gets stdin]

Онлайн-перекладачі просто смокчуть, щоб продемонструвати це, тоді я демонструю кілька зображень із командної оболонки Windows:

Тестовий випадок 1

введіть тут опис зображеннявведіть тут опис зображеннявведіть тут опис зображеннявведіть тут опис зображеннявведіть тут опис зображення

Тестовий випадок 2

введіть тут опис зображеннявведіть тут опис зображення введіть тут опис зображення


Чи можете ви пояснити це?
Adám

1
Я можу додати його зображення, що працюють у командному рядку Windows.
sergiol

@ Adám: Ви все ще хочете, щоб я пояснив, що робить код, чи зображень достатньо?
серхіол

Цього достатньо.
Адам

1

AHK , 32 байти

InputBox,s,,,,,,,,,,%1%
Send,%s%

InputBoxзберігає те, що вводиться як змінну, sі дає початковий запит змінної, 1яка є першим переданим параметром.
Sendнадсилає натискання клавіш на поточне вікно. У цьому випадку це буде вміст s.
MsgBoxбув варіант, але для гри в гольф на Send2 байти коротше.

Анімація


@ Adám Я неправильно прочитав цю частину. Я оновив відповідь.
Інженер Тост

Зараз це добре.
Адам

1

Команда негайних вікон Excel VBA - 22 байти

[a1]=inputbox(0,,[a1])

введіть тут опис зображення


2
Це лише часткове рішення, оскільки ваше початкове значення ("Привіт") жорстко кодується. Початкове значення потрібно звідкись прочитати (клітинку, підказку або файл ...), а кінцеве значення потрібно десь поставити (комірка, скринька повідомлень, файл, ...).
Adám

inputbox(0,,"Hi")рятує байт
Феліпе Нарді Батіста

@ Adám Дякую Виправлено зараз читання з клітини A1
Рохан

Я думаю, що тобі потрібно [a1]=inputbox(0,,[a1])чи щось, інакше, куди aйдеш? Збереження в змінній не є дійсним методом виводу .
Адам

Він іде туди, куди прийшов із клітини А1
Рохан

0

ZX Spectrum BASIC, 7 байт

Тривіальний, що додається для повноти ( INPUTі PRINTє одним байтовим жетоном кожен).

INPUT a$: PRINT a$

1
Як воно отримує початкове значення a$?
Adám

@ Adám він отримує початкове значення a$клавіатури; a$буде перезаписано INPUTключовим словом.
Shaun Bebbers

0

SmileBASIC, 138 байт

DEF E S@L
WAIT
B=BUTTON(1)C=C-(B==4&&C)+(B>7&&C<LEN(S))I$=INKEY$()IF"\u0008"<I$THEN B=I$<"\u000E"S=SUBST$(S,C,B,I$*!B)?S?" "*C;1IF"\u0008"!=I$GOTO@L
END

Створює функцію Eз 1 аргументом та 0 виходами. (Виведення відображається на консолі)

Символи, що втекли, повинні бути власне символами, але вони не відображатимуться тут.

Управління:

Normal keys: Insert a character before the cursor.
Enter: Delete the character at the cursor.
Backspace: Submit.
D-pad left: Move cursor left.
All buttons except up, down, and left on the d-pad: Move cursor right.

Вставлення / видалення символів відбувається назад, тому це дуже дратує використання (але все-таки повинно відповідати вимогам).

Just some text
1             
'(press right 5 times)
Just some text
     1
'(press enter 4 times)
Just  text
     1
'(press a)
Just a text
     1
'(press right)
Just a text
      1
'(...)
Just any text
       1
'(press backspace)

0

Інтерпретатор команд Windows, 16 байт

set/pa=
echo %a%

Це дуже банально; інтерпретатор команд є тривіально "редактором рядків".


0

Commodore BASIC (C64Mini, C64 / 128, VIC-20 тощо) 179 токенізованих байків BASIC

Це слід вводити в бізнес-режимі (великі та малі символи)

 0a$="Just some text":?"{SHIFT+CLR/HOME}"a$"_":fOi=0to1step0:getk$:on-(k$<>"")goS2:goS1:nE
 1?"{CTRL+N}{CLR/HOME}"a$"_  ";:return
 2ifasc(k$)<>20thena$=a$+k$:on-(asc(k$)=13)goS4:return
 3if-(len(a$))thena$=leF(a$,len(a$)-1):goS4:return
 4?"{ARROW LEFT}{ARROW LEFT}{ARROW LEFT}  ":return

Дозволяє основне редагування тексту + видалення + новий рядок. Максимальний розмір, a$як і всі рядки в Commodore BASIC, становить 255 символів, тому будь-який більше, ніж це, призведе до збою програми. Я знайду спосіб зробити> 255 символів, якщо це необхідно.

Простий симулятор типу "em-up"

Простий симулятор набору типу в дії

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.