code: function hint(ts, cm, c) {
      ts.request(cm, {type: "completions", types: true, docs: true, urls: true}, function(error, data) {
        if (error) return showError(ts, cm, error);
        var completions = [], after = "";
        var from = data.start, to = data.end;
        if (cm.getRange(Pos(from.line, from.ch - 2), from) == "[\"" &&
            cm.getRange(to, Pos(to.line, to.ch + 2)) != "\"]")
          after = "\"]";
  
        for (var i = 0; i < data.completions.length; ++i) {
          var completion = data.completions[i], className = typeToIcon(completion.type);
          if (data.guess) className += " " + cls + "guess";
          completions.push({text: completion.name + after,
                            displayText: completion.name,
                            className: className,
                            data: completion});
        }
  
        var obj = {from: from, to: to, list: completions};
        var tooltip = null;
        CodeMirror.on(obj, "close", function() { remove(tooltip); });
        CodeMirror.on(obj, "update", function() { remove(tooltip); });
        CodeMirror.on(obj, "select", function(cur, node) {
          remove(tooltip);
          var content = ts.options.completionTip ? ts.options.completionTip(cur.data) : cur.data.doc;
          if (content) {
            tooltip = makeTooltip(node.parentNode.getBoundingClientRect().right + window.pageXOffset,
                                  node.getBoundingClientRect().top + window.pageYOffset, content);
            tooltip.className += " " + cls + "hint-doc";
          }
        });
        c(obj);
      });
    }
docs: Completion