jscript模拟的“控制台”程序

类别:网站制作 点击:0 评论:0 推荐:

无聊的时候想到用jscript模拟Console程序,结果试了一下,觉得还蛮好玩的:P

实现了一个jscript“控制台”类

在读代码前先放出三个Demo:

http://akira.bigwww.com/Silver%20Luna/Demos/ConsoleDemo.html
通过“控制台”输入两个数求和

http://akira.bigwww.com/Silver%20Luna/Demos/ConsoleDemo2.html
通过“控制台”输入一个句子,统计字符类型和数量

http://akira.bigwww.com/Silver%20Luna/Demos/ConsoleDemo3.html
一个可以通过键盘敲入命令回车执行的模拟,还支持
begin
Codes...
end
的模式 :)

下面是程序代码:

//控制台类,模拟运行在控制台上的程序,可以控制“标准输入输出流”(程序模拟)
//使用方法:在页面上包含Console.js文件,构造Console对象,定义Main()函数,在Main函数中写控制命令
//版本:1.00
//作者:Akira
//编写日期:2004-11-19

function Console(page, consoleName)
{
        //静态成员
        Console.KEY_ENTER = 13;           //回车键
        Console.KEY_RETURN = 13;         //回车
        Console.KEY_NEWLINE = 10;            //换行
        Console.KEY_TAB = 9;                                    //TAB键
        Console.KEY_BACKSPACE = 8;            //退格键
        Console.KEY_LEFT = 37;                        //左移
        Console.KEY_RIGHT = 38;                        //右移
        Console.KEY_UP = 39;                                        //上移
        Console.KEY_DOWN = 40;                        //下移

        //初始化Page
        if (page == null)
        {
                page = self;
        }
        if (page != self)
        {
                //do sth here...
                throw new Error("参数错误:目前版本不支持为其他窗体对象初始化控制台\n请使用self参数");
        }
        this.page = page;

        //输入输出流属性,用字符串数组模拟流
        this.stream = new Object();
        this.stream.stdin = new Array(); //标准输入流
        this.stream.stdout = new Array(); //标准输出流
        this.stream.stderr = new Array(); //标准错误流

        this.stream.stdin.opened = false; //判断当前输入流是否开启,开启=允许写入
        this.stream.stdin.ReadOffset = 0; //判断当前输入流偏置,Read()方法使用
        this.stream.semaphores = 0; //流信号量,用来控制输出流显示,当调用输入函数时,信号量增加,
                                                                                         //当信号量大于stdin成员数目的时候,抛出异常阻塞标准输出流,用以模拟输入等待

        Console.prototype.Signal = function()
        {
                if(this.stream.semaphores == this.stream.stdin.length)
                {
                        return true;
                }
                if(this.stream.semaphores > this.stream.stdin.length)
                {
                        throw new WaitForInput(); //抛出异常阻止程序往下执行,用以等待输入
                }
                return false;
        }

        this.body = page.document.body;

        if (this.body == null)
        {
                throw new Error("控制台缺初始化失败,检查主体文档是否缺少BODY标记");
        }

        this.page.document.title += "——Javascript控制台";
        this.page.PageLoadEventSender = this;
        this.body.onload = function(){this.PageLoadEventSender.PageLoad(this.PageLoadEventSender,this.PageLoadEventSender.page.event);}  //定义PageLoad事件
        this.page.ResizeEventSender = this;
        this.body.onresize = function(){this.ResizeEventSender.OnResize(this.ResizeEventSender,this.ResizeEventSender.page.event);}

        this.ConsoleMain = page.document.getElementById(consoleName);          //可以通过参数指定初始化对象TEXTAREA的名称,这样可以把控制台
                                                                                                                                                                                                        //主窗口嵌入在网页中

        //如果没有指定获得TEXTAREA对象,则建立控制台主窗口,并让窗口占据整个页面
        if (this.ConsoleMain == null)                                                                                                                       
        {
                this.body.style.background = "#000000";
                this.page.document.bgColor = "#000000";
                this.ConsoleMain = page.document.createElement("textarea");
                page.document.body.appendChild(this.ConsoleMain);
                this.ConsoleMain.style.width="100%";
                this.ConsoleMain.style.height="100%";
                this.ConsoleMain.style.overflowX="hidden";
                this.ConsoleMain.style.overflowY="hidden";
                this.ConsoleMain.style.border="0px";
                this.ConsoleMain.style.background="#000000";
                this.ConsoleMain.style.color="C0C0C0";
        }

        if (this.ConsoleMain.tagName.toUpperCase() != "TEXTAREA")
        {
                throw new Error("控制台主窗口类型错误,主窗口对象必须为TEXTAREA类型");
        }

        this.ConsoleMain.KeyPressSender = this;                                //KeyPress事件
        this.ConsoleMain.onkeypress = function(){this.KeyPressSender.ConsoleMain_KeyPress(this.KeyPressSender, this.KeyPressSender.page.event);}
        this.ConsoleMain.KeyUpSender = this;                                        //KeyUp事件
        this.ConsoleMain.onkeyup = function(){this.KeyUpSender.ConsoleMain_KeyUp(this.KeyUpSender, this.KeyUpSender.page.event);}
        this.ConsoleMain.KeyDownSender = this;                        //KeyDown事件
        this.ConsoleMain.onkeydown = function(){return(this.KeyDownSender.ConsoleMain_KeyDown(this.KeyDownSender, this.KeyDownSender.page.event));}

        this.ConsoleMain.ClickSender = this;                //Click事件,用来避免光标位置随鼠标点击而改变
        this.ConsoleMain.onclick = function(){this.ClickSender.ConsoleMain_Click(this.ClickSender, this.ClickSender.page.event);}

        //Event Handlers
        Console.prototype.PageLoad = function(sender, event)          //PageLoad事件处理,调用this.Main()方法用来初始化控制台
        {
                //create frameConsole
                this.Main();
        }
        Console.prototype.OnResize = function(sender, event)           //Resize事件处理,将文字正确显示在控制台顶部
        {
                this.SetCursor();
        }
        Console.prototype.ConsoleMain_KeyDown = function(sender, event)
        {
                if (event.keyCode == Console.KEY_TAB)                //处理TAB键,避免主窗口失去焦点
                {
                        this.ConsoleMain.value += "\t";
                        if (!this.stream.stdin.opened)
                        {
                                this.stream.stdin.push("\t");
                                this.stream.stdin.opened = true;
                        }
                        else
                        {
                                this.stream.stdin[this.stream.stdin.length - 1] += "\t";
                        }
                        return false;
                }
                if (event.keyCode == Console.KEY_LEFT
                        ||event.keyCode == Console.KEY_RIGHT
                        ||event.keyCode == Console.KEY_UP
                        ||event.keyCode == Console.KEY_DOWN)    //忽略方向键,锁定光标
                {
                        return false;
                }
                return true;
        }
        Console.prototype.ConsoleMain_KeyUp = function(sender, event)
        {
                if (event.keyCode == Console.KEY_ENTER)                //处理回车键结束流的写入
                {
                        if(!this.stream.stdin.opened)                                                        //忽略空行和连续回车
                                return;
                        else
                        {
                                this.stream.stdin.opened = false;
                                this.Main();                                                                                                //结束流的写入,并让程序继续往下执行
                        }
                }
                if (event.keyCode == Console.KEY_BACKSPACE)           //处理退格键
                {
                        if (!this.stream.stdin.opened)                                                        //忽略当前流为空时的退格键
                        {
                                return;                                                                                                               
                        }
                        else
                        {
                                if (this.stream.stdin[this.stream.stdin.length - 1].length == 0)
                                {
                                        return;
                                }
                                this.stream.stdin[this.stream.stdin.length - 1] = this.stream.stdin[this.stream.stdin.length - 1].substr(0, this.stream.stdin[this.stream.stdin.length - 1].length - 1);
                                if (this.stream.stdin[this.stream.stdin.length - 1].length == 0)
                                {
                                        this.stream.stdin.length--;
                                        this.stream.stdin.opened = false;
                                }
                        }
                }
        }
        Console.prototype.ConsoleMain_KeyPress = function(sender, event)                //键盘事件,将字符写入流
        {
                if (!this.stream.stdin.opened) //New Stream
                {
                        if (event.keyCode != Console.KEY_ENTER)
                        {
                                this.stream.stdin.push(String.fromCharCode(event.keyCode));
                                this.stream.stdin.opened = true;
                        }
                }
                else
                {
                        if (event.keyCode != Console.KEY_ENTER)
                                this.stream.stdin[this.stream.stdin.length - 1] += String.fromCharCode(event.keyCode);
                }
        }
        Console.prototype.ConsoleMain_Click = function(sender, event)
        {
                this.SetCursor();
        }
        //Methods
        Console.prototype.init = function()                                                                        //初始化方法,在this.Main()中被调用
        {
                //this.ConsoleMain.value="控制台初始化完成...\n";
                this.ConsoleMain.contentEditable = true;
                this.stream.semaphores = 0;
                this.stream.stdin.ReadOffset = 0;
                this.stream.stdin.opened = false;
        }
        Console.prototype.WriteLine = function(msg)                                                //写入一行文本到标准输出流
        {
                if (this.Signal())
                {
                        this.ConsoleMain.value+=msg+"\n";
                        this.stream.stdout.push(msg+"\n");
                }
        }
        Console.prototype.Write = function(msg)                                                        //写入一个字符串到标准输出流
        {
                if (this.Signal())
                {
                        this.ConsoleMain.value+=msg;
                        this.stream.stdout.push(msg);
                }
        }
        Console.prototype.Error = function(msg)                                                        //写入错误信息到标准错误流
        {
                if (this.Signal())
                {
                        this.ConsoleMain.value+=msg;
                        this.stream.stderr.push(msg);
                }
        }
        Console.prototype.ReadLine = function()                                                        //从标准输入流读取一行
        {
                if (this.Signal())
                {
                        this.SetCursor();                                                                                                        //光标移至输入位置
                        throw new WaitForInput();                                                                                //抛出异常阻止程序往下执行,用以等待输入
                }
                this.stream.semaphores++;
                if (this.stream.semaphores <= this.stream.stdin.length)
                {
                        if (isNaN(this.stream.stdin[this.stream.semaphores - 1])) //非数字返回对象
                        {
                                return this.stream.stdin[this.stream.semaphores - 1];
                        }
                        else
                        {
                                return this.stream.stdin[this.stream.semaphores - 1] - 0; //数字返回数值
                        }
                }
        }
        Console.prototype.SetCursor = function()
        {
                this.ConsoleMain.focus();
                var range = this.ConsoleMain.createTextRange();
                range.moveStart('character',this.ConsoleMain.value.lenght);
                range.collapse(false);
                range.select();       
        }

        Console.prototype.Read = function() //从标准输入流读取下一个字符
        {
                if (this.Signal() && this.stream.stdin.ReadOffset == 0)
                {
                        this.ConsoleMain.focus();
                        var range = this.ConsoleMain.createTextRange();
                        range.moveStart('character',this.ConsoleMain.value.lenght);
                        range.collapse(false);
                        range.select();
                        this.stream.stdin.push("");
                        this.stream.stdin.opened=true;
                        throw new WaitForInput(); //抛出异常阻止程序往下执行,用以等待输入
                }
                else if (this.stream.semaphores <= this.stream.stdin.length)
                {
                        if (this.stream.stdin.ReadOffset == 0)        //读取流的第一个字符,信号量增加
                        {
                                this.stream.semaphores++;
                        }
                        if (this.stream.stdin.ReadOffset < this.stream.stdin[this.stream.semaphores - 1].length)
                        {
                                        return this.stream.stdin[this.stream.semaphores - 1].charCodeAt(this.stream.stdin.ReadOffset++);
                        }
                        else if(this.stream.stdin.ReadOffset == this.stream.stdin[this.stream.semaphores - 1].length)   //恢复在流的末尾被忽略的回车和换行
                        {
                                        this.stream.stdin.ReadOffset++;
                                        return Console.KEY_RETURN;
                        }
                        else if(this.stream.stdin.ReadOffset == this.stream.stdin[this.stream.semaphores - 1].length + 1)
                        {
                                        this.stream.stdin.ReadOffset=0;
                                        return Console.KEY_NEWLINE;
                        }
                        else
                        {
                                throw new Error("Stack over flow! Read Error!");
                        }
                }
        }
        Console.prototype.Main = function()
        {
                this.init();
                try
                {
                        Main();
                        if (this.Signal())
                        {
                                this.Dispose();
                        }
                }
                catch(e)
                {
                        if (e instanceof WaitForInput)
                        {

                        }
                        else
                        {
                                this.Error("错误:" + e.number + "," + e.name + ":" + e.message);                //将错误信息写入标准错误流
                                this.Dispose();
                        }
                }
        }
        Console.prototype.Dispose = function()                //结束控制台流程,按任意键关闭窗口
        {
                                this.ConsoleMain.contentEditable = false;
                                this.ConsoleMain.focus();
                                this.Write("\nPress any key to continue...\n");
                                this.ConsoleMain.KeyDownSender = this;
                                this.ConsoleMain.onkeydown = function(){this.KeyDownSender.page.close();return false;}
        }
}

//等待输入的“异常”类,用来在要求用户输入的时候阻塞程序的运行。
function WaitForInput()
{

}WaitForInput.prototype = new Error();

//调试控制台——可运行和调试javascript程序段
//版本:0.01 Demo
//作者:Akira
//日期:2004-11-19
function DebugConsole()
{
        DebugConsole.prototype.RunCommand = function(command)
        {
                        if (this.Signal())
                        {
                                var regexp = new RegExp("document.writeln","g");
                                command = command.replace(regexp, "this.WriteLine");
                                regexp = new RegExp("document.write","g");
                                command = command.replace(regexp, "this.Write");
                                try
                                {
                                        eval(command);
                                }
                                catch(e)
                                {
                                        this.Error("指令无效:" + e.number + "," + e.name + ":" + e.message + "\n");
                                }
                        }
        }
        DebugConsole.prototype.Start = function()
        {
                this.WriteLine("调试控制台初始化...完成!");
                var command = "";
                var process = "";
                var runProc = false;

                while ((command = this.ReadLine()) != "stop")
                {
                        if (command == "begin")
                        {
                                process="";
                                runProc = true; //执行一组命令
                                continue;
                        }
                        if (command == "end")
                        {
                                this.RunCommand(process);
                                runProc = false;
                                continue;
                        }
                        if (command.charAt(0) == "=")
                        {
                                command = "this.WriteLine(" + command.substring(1) + ");";
                        }
                        if (!runProc)
                        {
                                this.RunCommand(command); //执行一条命令
                        }
                        else
                        {
                                process += command;
                        }
                }
        }
}DebugConsole.prototype = new Console();

//这个控制台目前的缺点是:1)异常信息无法显示行号 2)不能在新开窗口中动态建立控制台
//有待改进......

本文地址:http://com.8s8s.com/it/it30747.htm