创建一个简单的行编辑器


19

输入:不带换行符的字符串*
允许用户编辑和提交换行符
:修改后的字符串(可选带尾随的换行符)

行编辑器至少必须允许用户:

  1. 左右移动可见光标

  2. 在光标位置插入和/或覆盖字符

  3. 删除光标位置的字符

  4. 提交新的字符串,即停止编辑会使修改后的字符串返回/打印/显示/保存(没有其他文本)

赞赏,但不是必需的:

  • 您的代码的解释。

  • 链接到可以演示您的程序/功能的在线测试站点

  • 演示用法的动画图像(例如,TIO不允许交互)

注意:

  • 键绑定仅是建议

  • 不需要GUI或视觉样式

例子

在下面,用表示光标_。

进入: Just some text
允许用户编辑:
 Just some text_  用户按下←九次(向左箭头键)
 Just ̲some text  用户按下Del四次
 Just ̲ text  用户按下 用户按下Out:any
 Just any_text Enter
Just any text

入: Remove me
允许用户编辑:
 Remove me_  用户按Backspace九次
 _  用户按出:(空字符串)Enter
 


*为了避免琐碎的编辑器解决方案,必须通过与编辑命令不同的输入法来提供此解决方案,或者必须使用换行符或类似的命令将它们与它们分开。


我们是否必须将这些确切的按键用于I / O?另外,我们可以创建一个文件来保存文本吗?
— Rɪᴋᴇʀ

1
@Riker 键绑定仅是建议。输入和输出方法遵循PPCG的默认设置。
— 亚当

字符串可以包含换行符吗?换行符可以用来“提交”吗?
— Conor O'Brien

@ ConorO'Brien否;简单的行编辑器。是; 编辑必须至少允许用户:(......)4.提交新的字符串
— 亚当

1
如果您在问题的实际正文中指定了行,将是很好的,因为此站点上的标题并不完全是规范...
— Conor O'Brien

Answers:



8

JavaScript(ES6),15个 14字节

我不明白为什么这么多的赞!

s=>prompt(s,s)

由于Adám建议我将原始输入显示在中,因此节省了一个字节prompt。


尝试一下

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


1
""用0甚至替换来保存一个字节s(这样,用户在编辑时仍然可以看到原始文本-简洁的功能)。
— 亚当

5

Bash 4.x,25个字符

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

样品运行:

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

(上面的第二行是交互式编辑,第三行是结果文本的输出。)


1
对我来说不行-bash: read: -i: invalid option吗?man说只ers允许标志。
— Rɪᴋᴇʀ

是啊,我正要询问-ei
— 亚当

-i是在Bash 4.0(2009年2月发布)中引入的–“ -i text使用TEXT作为Readline的初始文本”。
— manatwork '17

我想知道猫会工作吗?
— 马修·卢

cat只是等待传入的流,shell将不提供任何编辑功能。至少不是默认情况下。
— manatwork '17

3

Bash + Vi / Vim,14个字节

echo $1>a;vi a

vi是vimmacOS 上的别名,我不了解其他操作系统。


也许我遗漏了一些东西,但这是否满足输出修改后的字符串的要求?
— 格雷森·肯特

1
@GraysonKent您可以通过单击:wq!或保存并退出:x,所以我认为是。OP在什么条件上尚不清楚。
— 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;

感谢JörgHülsermann,节省了10个字节;感谢Luke,节省了2个字节。

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

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


2
您可以删除input元素的类型attribut
— 约尔格Hülsermann

您可能应该使用oninput代替。
— 马修·罗

@SIGSEGV我认为按下oninput时不会触发Enter
— 汤姆(Tom)

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]以完成编辑
其他任何键都将插入文本

例:

使用OP的例子

进入: 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非常好。实际实现一个真正的编辑器的第一个答案,而不是依赖于预先存在的功能。我正在考虑发布另一个挑战来做到这一点。
— 亚当

您不能通过使用其他左右键来保存字节吗?
— 亚当

我可以假设字符-和+这样做,但编辑器将无法接受这些字符,那么
— 菲利普·纳迪巴蒂斯塔

如何\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。

enter image description here

enter image description here

  • 按九次向左箭头按钮。

enter image description here

  • 按下删除按钮四次。

enter image description here

  • 按下a然后n再y。

enter image description here

  • 按Enter终止。

enter image description here

详细

#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_*相应的整数代替来节省一些字节吗?
— sergiol


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 demo


2

Ruby,9 19 22 84字节

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

这将创建一个Readline预输入钩子,该钩子将插入文本s,然后重新显示。在此之后,irb陷入混乱,因此请确保从文件中运行它。作为lambda运行,它将输入字符串作为参数并返回输出字符串。

puts Readline.readline

这将使用Readline库执行行编辑。我以前的回答只允许使用退格键。

puts gets

这是真的,真的是自我解释。

编辑:我被要求提供解释。等同于puts(gets)。gets用行编辑器输入一个字符串。puts输出它。


链接方法调用:r.insert_text(s).redisplay并删除以下内容;。顺便说一句,据我了解我们的政策,您应该提到您的代码在中运行irb,因为否则您将需要Readline在代码中进行要求。
— manatwork '17

1

PHP + HTML,26字节

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

浏览器会自动添加结束标记

$ _GET使用类似http://example.com?0=input输入的URL 在HTML中创建<input value=input

这是字符串输入的输出

<input value=input


我应该认为这可行吗?也许您可以添加说明,链接或动画?
— 亚当

@Adám是的,您可以假设可能会有所改善,并设置属性autofocus以使其光标位于开始位置。如果设置了属性,您还可以编辑其他HTML元素contenteditable
— 约尔格Hülsermann

输入=test></input><script>alert("Hi");//some malicious code\n</script>
— RomanGräf17年

@RomanGräf坏男孩。是的,它是更好的过滤器的Javascript
— 约尔格Hülsermann

1

Tcl,17

puts [gets stdin]

在线解释器只是想演示一下,然后我展示了Windows命令外壳中的一些图像:

测试用例1

enter image description hereenter image description hereenter image description hereenter image description hereenter image description here

测试案例2

enter image description hereenter image description here enter image description here


你能解释一下吗?
— 亚当

1
我可以添加在Windows命令行上运行的图像。
— sergiol

@Adám:您是否仍要我解释代码的作用或图像是否足够?
— sergiol

这就够了。
— 亚当

1

AHK,32字节

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

InputBox存储键入的任何内容作为变量,s并给出该变量的启动提示,1这是第一个传递的参数。
Send将击键发送到当前窗口。在这种情况下,它将是的内容s。
MsgBox是一个选项,但是对于高尔夫来说,Send短2个字节。

Animation


@Adám我误读了那部分。我已经更新了答案。
— Engineer Toast

现在很好。
— 亚当

1

Excel VBA立即窗口命令-22字节

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

enter image description here


2
这只是部分解决方案,因为您的初始值(“ Hi”)是硬编码的。初始值必须从某个位置(单元格,提示或文件...)读取,最终值必须置于某个位置(单元格,消息框,文件等)。
— 亚当

inputbox(0,,"Hi")保存一个字节
— Felipe Nardi Batista

@Adám谢谢。现在已修复,它正在从单元格A1中读取
— Rohan

我认为您需要[a1]=inputbox(0,,[a1])什么,否则,哪里a去了?存储在变量中不是有效的输出方法。
— 亚当

它从单元格A1到达的地方
— Rohan

0

ZX Spectrum BASIC,7个字节

平凡的,为了完整性INPUT而包含(PRINT每个都是一个字节的令牌)。

INPUT a$: PRINT a$

1
它如何获得的初始值a$?
— 亚当

@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个字符。

Simple type-em-up simulator

Simple type-em-up simulator in action

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.