Skip to content

Instantly share code, notes, and snippets.

@echojc
Created June 18, 2017 09:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save echojc/c84002a0256574ea927b5406df744e62 to your computer and use it in GitHub Desktop.
Save echojc/c84002a0256574ea927b5406df744e62 to your computer and use it in GitHub Desktop.
<!doctype html>
<html>
<head>
<title>vim demo</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.min.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet">
<style>
html,
body {
height: 100%;
}
body {
display: flex;
flex-direction: column;
align-items: center;
background-color: #34495e;
}
textarea#t {
border: 0;
outline: 0;
padding: 4px;
margin: 0;
width: 100%;
height: 100%;
font-size: 14px;
line-height: 18px;
font-family: 'Source Code Pro', monospace;
color: #f0f0f0;
background-color: #2c3e50;
resize: none;
white-space: nowrap;
overflow: auto;
box-sizing: border-box;
}
input#c {
position: fixed;
left: 0;
bottom: 0;
width: 100%;
border: 0;
border-top: 1px solid #34495e;
outline: 0;
padding: 4px;
margin: 0;
font-size: 14px;
line-height: 18px;
font-family: 'Source Code Pro', monospace;
color: #f0f0f0;
background-color: #2c3e50;
box-sizing: border-box;
}
</style>
</head>
<body>
<textarea id="t" spellcheck="false">
type scrapeConfig struct {
FetchMinInterval time.Duration
FetchMaxInterval time.Duration
MetadataRefreshInterval time.Duration
TopicsFilter *regexp.Regexp
GroupsFilter *regexp.Regexp
}
func mustNewScrapeConfig(refresh time.Duration, fetchMin time.Duration, fetchMax time.Duration, topics string, groups string) scrapeConfig {
topicsFilter, err := regexp.Compile(topics)
if err != nil {
log.Fatal(err)
}
// empty group should match nothing instead of everything
if groups == "" {
groups = ".^"
}
groupsFilter, err := regexp.Compile(groups)
if err != nil {
log.Fatal(err)
}
return scrapeConfig{
FetchMinInterval: fetchMin,
FetchMaxInterval: fetchMax,
MetadataRefreshInterval: refresh,
TopicsFilter: topicsFilter,
GroupsFilter: groupsFilter,
}
}
func startKafkaScraper(wg *sync.WaitGroup, shutdown chan struct{}, kafka sarama.Client, cfg scrapeConfig) {
go refreshMetadataPeriodically(wg, shutdown, kafka, cfg)
for _, broker := range kafka.Brokers() {
go manageBroker(wg, shutdown, broker, kafka, cfg)
}
}
</textarea>
<input id="c" />
<script language="javascript">
window.onload = function() {
var target = document.getElementById('t');
var command = document.getElementById('c');
window.vim = new Vim(target, command);
};
var Vim = (function() {
function Vim(target, command) {
this.mode = 'normal';
this.line = 0;
this.col = 0;
target.addEventListener('keydown', this.keydown.bind(this));
target.addEventListener('click', this.click.bind(this));
this.target = target;
command.addEventListener('keydown', this.commandKeydown.bind(this));
this.command = command;
this.resetCommand();
this.settings = {
tabstop: 8,
};
this.syncSettings();
this.target.focus();
}
Vim.prototype.syncSettings = function() {
this.target.style.tabSize = this.settings.tabstop;
};
Vim.prototype.fromOffset = function() {
var lines = this.target.value.substring(0, this.target.selectionStart).split('\n');
var line = lines.length - 1;
return { line: line, col: lines[line].length };
};
Vim.prototype.copyOffsetToLineCol = function() {
var lc = this.fromOffset();
this.line = lc.line;
this.col = lc.col;
};
Vim.prototype.copyLineColToOffset = function() {
var re = new RegExp('^([^\n]*\n){' + this.line + '}');
var result = re.exec(this.target.value);
if (!result) {
this.target.selectionStart = this.target.value.length;
} else {
var lineStart = result[0].length;
var desiredCol = lineStart + this.col;
var containedNewLine = this.target.value.substring(lineStart, desiredCol).indexOf('\n');
if (containedNewLine === -1) {
this.target.selectionStart = desiredCol;
} else {
this.target.selectionStart = lineStart + containedNewLine;
}
}
};
Vim.prototype.keydown = function(e) {
switch (this.mode) {
case 'normal':
e.preventDefault();
switch (e.key) {
case 'F5':
window.location.reload();
break;
case 'h':
var lc = this.fromOffset();
this.col = Math.max(0, lc.col - 1);
this.copyLineColToOffset();
break;
case 'j':
var lc = this.fromOffset();
this.line = lc.line + 1;
this.copyLineColToOffset();
break;
case 'k':
var lc = this.fromOffset();
this.line = Math.max(0, lc.line - 1);
this.copyLineColToOffset();
break;
case 'l':
var lc = this.fromOffset();
this.col = lc.col + 1;
this.copyLineColToOffset();
break;
case ':':
this.showCommand();
this.command.value = ':';
this.command.focus();
}
break;
}
this.render();
};
Vim.prototype.click = function(e) {
this.copyOffsetToLineCol();
this.resetCommand();
};
Vim.prototype.render = function() {
switch (this.mode) {
case 'normal':
start = this.target.selectionStart;
this.target.setSelectionRange(start, start + 1, 'none');
break;
}
};
Vim.prototype.resetCommand = function() {
this.command.value = '';
this.command.style.display = 'none';
};
Vim.prototype.showCommand = function() {
this.command.style.display = 'inline';
};
Vim.prototype.commandKeydown = function(e) {
switch (e.key) {
case 'Enter':
e.preventDefault();
var cmd = this.command.value;
this.resetCommand();
this.target.focus();
this.run(cmd);
break;
case 'Escape':
e.preventDefault();
this.resetCommand();
this.target.focus();
break;
}
};
Vim.prototype.run = function(cmd) {
var argv = cmd.replace(/^:\s*/, '').split(/\s+/);
switch (argv[0]) {
case 'set':
for (var i = 1; i < argv.length; i++) {
var split = argv[i].split('=');
switch (split[0]) {
case 'ts':
case 'tabstop':
this.settings.tabstop = parseInt(split[1], 10);
break;
}
}
this.syncSettings();
break;
}
};
return Vim;
})();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment