shen_web.init_repl = function() {
  shen_web.set_init_status("Initializing repl");
  var line_buffer = [],
      buffer_index = 0,
      repl = {};
  function puts(str, tag) {
    var cont = repl.out.parentNode,
        sd = cont.scrollHeight - cont.scrollTop,
        diff = Math.abs(sd - cont.clientHeight),
        t = document.createTextNode(str);
    if (tag) {
      var s = document.createElement("span");
      s.className = "repl_tag_" + tag;
      s.appendChild(t);
      repl.out.insertBefore(s, repl.inp);
    } else
      repl.out.insertBefore(t, repl.inp);
    repl.out.normalize();
    if (diff < 5)
      cont.scrollTop = cont.scrollHeight;
  }

  function init_input() {
    var t = document.getElementById("repl_in"),
        b = document.getElementById("repl_in_send"),
        out = document.getElementById("repl_out");

    repl.inp = t;
    repl.out = out;

    repl.inp.contentEditable = true;
    repl.inp.spellcheck = false;
    repl.out.onclick = function() {
      if (document.activeElement !== repl.inp)
        repl.inp.focus();
    };

    repl.inp.onkeyup = function(e) {
      var key = e.keyCode || e.which;
      if (key == 0xd && !e.ctrlKey) {
        var line = repl.inp.textContent || repl.inp.innerText;
        line = line.trimRight("\n");
        shen_web.send(line + "\n");
        shen_web.clean(repl.inp);

        if (line_buffer.length == 0
            || line != line_buffer[line_buffer.length - 1]) {
          line_buffer.push(line);
        }
        buffer_index = line_buffer.length;
        return true;
      } else if (key == 0x26) {
        if (buffer_index > 0) {
          var new_text = line_buffer[--buffer_index];
          repl.inp.textContent = new_text;
        }
      } else if (key == 0x28) {
        if (buffer_index < line_buffer.length) {
          buffer_index++;
          repl.inp.textContent = line_buffer[buffer_index];
        }
      }
      return false;
    };
  }

  shen_web.puts = puts;
  shen_web.init_maximize(document.getElementById("repl"));
  shen_web.repl = repl;
  init_input();
};

@@ -655,16 +655,407 @@
 t;%0A  %7D%0A%0A
+  function set_caret_pos(off) %7B%0A    var range = document.createRange(),%0A        sel = window.getSelection(),%0A        obj = repl.inp.childNodes%5B0%5D,%0A        t;%0A    if (!obj)%0A      return;%0A    if (off === undefined)%0A      off = (repl.inp.textContent %7C%7C repl.inp.innerText).length;%0A    range.setStart(obj, off);%0A    range.collapse(true);%0A    sel.removeAllRanges();%0A    sel.addRange(range);%0A  %7D%0A%0A
   functi
@@ -2098,24 +2098,51 @@
 = new_text;%0A
+          set_caret_pos();%0A
         %7D%0A  
@@ -2298,32 +2298,59 @@
 %5Bbuffer_index%5D;%0A
+          set_caret_pos();%0A
         %7D%0A      

Fix caret position when navigating input history.