Rework auto-availability of binaries

This commit is contained in:
Rudra Saraswat 2023-05-02 23:54:00 +05:30
parent 956e8eb1b5
commit eea89f26cc
5 changed files with 154 additions and 107 deletions

View file

@ -24,7 +24,7 @@ function createWindow() {
autoHideMenuBar: true autoHideMenuBar: true
}) })
mainWindow.setMenu(null) // mainWindow.setMenu(null)
mainWindow.loadFile('src/index.html') mainWindow.loadFile('src/index.html')
} }
@ -75,6 +75,7 @@ function loadTerminalWindow(title, cmd) {
terminalWindow.show() terminalWindow.show()
ipcMain.removeAllListeners('terminal.reset') ipcMain.removeAllListeners('terminal.reset')
ipcMain.removeAllListeners('terminal.resize')
ipcMain.removeAllListeners('terminal.keystroke') ipcMain.removeAllListeners('terminal.keystroke')
ipcMain.removeAllListeners('terminal.incomingData') ipcMain.removeAllListeners('terminal.incomingData')
ipcMain.removeAllListeners('title') ipcMain.removeAllListeners('title')

View file

@ -7,9 +7,9 @@ function init_waydroid() {
require('child_process').spawnSync('pkexec', ['systemctl', 'enable', '--now', 'waydroid-container']) require('child_process').spawnSync('pkexec', ['systemctl', 'enable', '--now', 'waydroid-container'])
require('child_process').spawn('sh', ['-c', 'waydroid session start & disown']) require('child_process').spawn('sh', ['-c', 'waydroid session start & disown'])
setTimeout(() => { setTimeout(() => {
require('child_process').spawnSync('waydroid', ['prop', 'set', 'persist.waydroid.multi_windows', 'true']) require('child_process').spawnSync('sh', ['-c', 'echo "persist.waydroid.multi_windows=true" | pkexec tee -a /var/lib/waydroid/waydroid_base.prop'])
require('child_process').spawnSync('pkexec', ['waydroid', 'shell', 'pm', 'disable', 'com.android.inputmethod.latin']) require('child_process').spawnSync('pkexec', ['waydroid', 'shell', 'pm', 'disable', 'com.android.inputmethod.latin'])
if (require('child_process').spawnSync('sh', ['-c', 'LC_ALL=C glxinfo | grep "^OpenGL renderer string: "']).stdout.includes('NVIDIA')) { if (require('child_process').spawnSync('sh', ['-c', 'LC_ALL=C glxinfo | grep "^OpenGL renderer string: "']).stdout.includes('NVIDIA') || require('child_process').spawnSync('cat', ['/proc/cpuinfo']).stdout.includes('hypervisor')) {
require('child_process').spawnSync('sh', ['-c', 'echo "ro.hardware.gralloc=default" | pkexec tee -a /var/lib/waydroid/waydroid.cfg']) require('child_process').spawnSync('sh', ['-c', 'echo "ro.hardware.gralloc=default" | pkexec tee -a /var/lib/waydroid/waydroid.cfg'])
require('child_process').spawnSync('sh', ['-c', 'echo "ro.hardware.egl=swiftshader" | pkexec tee -a /var/lib/waydroid/waydroid.cfg']) require('child_process').spawnSync('sh', ['-c', 'echo "ro.hardware.egl=swiftshader" | pkexec tee -a /var/lib/waydroid/waydroid.cfg'])
} }

View file

@ -1,21 +1,27 @@
var term var term
function open_container(name) { function open_container(name) {
ipc.send("create-term", { 'title': `Container: ${name}`, 'cmd': `blend enter -cn ${name}` }); ipc.send("create-term", { 'title': `Container: ${name}`, 'cmd': `BLEND_NO_CHECK=true blend enter -cn ${name}` });
} }
function create_container () { function create_container() {
$('#inputContainerName').on('input', () => {
$('#inputContainerName').get(0).setCustomValidity('')
$('#inputContainerName').get(0).reportValidity();
})
container_name = $('#inputContainerName').val() container_name = $('#inputContainerName').val()
if (!(/^[\w\-\.]+$/.test(container_name))) { if (!(/^[\w\-]+$/.test(container_name))) {
$('#inputContainerName').get(0).setCustomValidity('Container name can only contain alphanumeric characters and dashes (no spaces allowed).') $('#inputContainerName').get(0).setCustomValidity('Container name may only contain alphanumeric characters and dashes (no spaces allowed).')
$('#inputContainerName').get(0).reportValidity(); $('#inputContainerName').get(0).reportValidity();
return return
} }
container_distro = $('#inputContainerDistro').val().toLowerCase().replace(' ', '-') container_distro = $('#inputContainerDistro').val().toLowerCase().replace(' ', '-')
ipc.send("create-term", { 'title': `Creating container: ${container_name}`, ipc.send("create-term", {
'cmd': `blend create-container -cn ${container_name} -d ${container_distro} \ 'title': `Creating container: ${container_name}`,
&& echo 'created container successfully (exiting automatically in 5 seconds)' \ 'cmd': `blend create-container -cn ${container_name} -d ${container_distro} \
|| echo 'container creation failed (exiting automatically in 5 seconds)'; && echo -e '\nExiting automatically in 5 seconds.' \
|| echo -e '\nContainer creation failed. Exiting automatically in 5 seconds.';
sleep 5` }) sleep 5` })
$('#inputContainerName').val('') $('#inputContainerName').val('')
ipc.on('container-created', () => { ipc.on('container-created', () => {
@ -23,7 +29,7 @@ function create_container () {
}) })
} }
async function remove_container (name) { async function remove_container(name) {
let rm_worker = new Worker( let rm_worker = new Worker(
`data:text/javascript, `data:text/javascript,
require('child_process').spawnSync('podman', ['stop', '-t', '0', '${name}'], { encoding: 'utf8' }) require('child_process').spawnSync('podman', ['stop', '-t', '0', '${name}'], { encoding: 'utf8' })
@ -37,47 +43,7 @@ async function remove_container (name) {
window.worker = new Worker( window.worker = new Worker(
`data:text/javascript, `data:text/javascript,
function list_containers() { function list_containers() {
let container_list = require('child_process').spawnSync('podman', ['ps', '-a', '--no-trunc', '--size', '--format', '{{.Names}}'], { encoding: 'utf8' }).stdout.split(/\\r?\\n/).filter(Boolean).reverse(); return require('child_process').spawnSync('podman', ['ps', '-a', '--no-trunc', '--size', '--format', '{{.Names}}'], { encoding: 'utf8' }).stdout.split(/\\r?\\n/).filter(Boolean).reverse();
if (require('fs').existsSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), 'utf8')) {
try {
let fileContents = require('fs').readFileSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), 'utf8')
let data = require('js-yaml').load(fileContents);
new_container_list = data['container_order']
container_list.forEach(container => {
if (!new_container_list.includes(container)) {
new_container_list.push(container)
}
});
new_container_list = new_container_list.filter(container => container_list.includes(container))
new_container_list.filter((item, index) => arr.indexOf(item) === index)
data = {
container_order: [...new_container_list],
use_container_bins: []
};
contents = require('js-yaml').dump(data)
require('fs').writeFileSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), contents, 'utf8')
return new_container_list
} catch (e) {
let data = {
container_order: [...container_list],
use_container_bins: []
};
contents = require('js-yaml').dump(data)
require('fs').writeFileSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), contents, 'utf8')
return container_list
}
} else {
let data = {
container_order: [...container_list],
use_container_bins: []
};
require('fs').mkdirSync(require('path').join(require('os').homedir(), '.config/blend'), { recursive: true });
contents = require('js-yaml').dump(data)
require('fs').writeFileSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), contents, 'utf8')
return container_list
}
} }
function truncateText(text, maxLength=30) { function truncateText(text, maxLength=30) {
@ -98,7 +64,7 @@ window.worker = new Worker(
<div class="row align-items-center"> <div class="row align-items-center">
<div class="col"> <div class="col">
<strong class="mb-0">No containers present.</strong> <strong class="mb-0">No containers present.</strong>
<p class="text-muted mb-0">Create one from below.</p> <p class="text-muted mb-0">Create one from above.</p>
</div> </div>
</div> </div>
</div> </div>
@ -108,25 +74,19 @@ window.worker = new Worker(
container_list.forEach(container => { container_list.forEach(container => {
container_list_html += \` container_list_html += \`
<div class="list-group-item" style="padding-top: 10px; padding-bottom: 10px; border: 0.5px solid rgba(255, 255, 255, 0.05);"> <div class="list-group-item" style="padding: 11px 20px 11px 20px; border: 0.5px solid rgba(255, 255, 255, 0.05);">
<div class="row align-items-center" style="cursor: grab;"> <div class="row align-items-center">
<div class="col"> <div class="col">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-grip-vertical" viewBox="0 0 16 16" style="margin-right: 12px;">
<path d="M7 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
</svg>
<strong class="mb-0 container_name">\${container}</strong> <strong class="mb-0 container_name">\${container}</strong>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-play" viewBox="0 0 16 16" onclick="open_container('\${container}')" style="cursor: pointer; margin-right: 8px;"> <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-play" viewBox="0 0 16 16" onclick="open_container('\${container}')" style="cursor: pointer; margin-right: 8px;">
<path d="M10.804 8 5 4.633v6.734L10.804 8zm.792-.696a.802.802 0 0 1 0 1.392l-6.363 3.692C4.713 12.69 4 12.345 4 11.692V4.308c0-.653.713-.998 1.233-.696l6.363 3.692z"/> <path d="M10.804 8 5 4.633v6.734L10.804 8zm.792-.696a.802.802 0 0 1 0 1.392l-6.363 3.692C4.713 12.69 4 12.345 4 11.692V4.308c0-.653.713-.998 1.233-.696l6.363 3.692z"/>
</svg> </svg>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16" onclick="remove_container('\${container}')" style="cursor: pointer; margin-right: 20px; z-index: 10;"> <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16" onclick="remove_container('\${container}')" style="cursor: pointer; z-index: 10;">
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/> <path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/> <path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
</svg> </svg>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-grip-vertical" viewBox="0 0 16 16">
<path d="M7 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
</svg>
</div> </div>
</div> </div>
</div> </div>
@ -155,31 +115,98 @@ worker.postMessage('update-list')
worker.onmessage = function (event) { worker.onmessage = function (event) {
window.data = event.data window.data = event.data
if (event.data.includes('bi-grip-vertical')) { $('#container-list').html(event.data)
$('#container-list').addClass('sortable') }
$('#container-list').html(event.data)
} else { function create_association() {
$('#container-list').removeClass('sortable') $('#inputAssociationContainerName').on('input', () => {
$('#container-list').html(event.data) $('#inputAssociationContainerName').get(0).setCustomValidity('')
$('#inputAssociationContainerName').get(0).reportValidity();
})
$('#inputAssociationBinaryName').on('input', () => {
$('#inputAssociationBinaryName').get(0).setCustomValidity('')
$('#inputAssociationBinaryName').get(0).reportValidity();
})
if (!(/^[\w\-]+$/.test($('#inputAssociationContainerName').val()))) {
$('#inputAssociationContainerName').get(0).setCustomValidity('Container name may only contain alphanumeric characters and dashes (no spaces allowed).')
$('#inputAssociationContainerName').get(0).reportValidity();
return
} }
$('.sortable').each((i, e) => { if (!(/^[\w\-]+$/.test($('#inputAssociationBinaryName').val()))) {
Sortable.create(e, { $('#inputAssociationBinaryName').get(0).setCustomValidity('Binary name may only contain alphanumeric characters and dashes (no spaces allowed).')
animation: 100, $('#inputAssociationBinaryName').get(0).reportValidity();
onEnd: () => { return
let container_list = [] }
$('.container_name').each((i, e) => {
container_list.push(e.innerText) if (binary_names.includes($('#inputAssociationBinaryName').val())) {
}) $('#inputAssociationBinaryName').get(0).setCustomValidity('Association already exists.')
let data = { $('#inputAssociationBinaryName').get(0).reportValidity();
container_order: [...container_list], return
use_container_bins: [] }
};
require('fs').mkdirSync(require('path').join(require('os').homedir(), '.config/blend'), { recursive: true }); fs.appendFile(require('os').homedir() + '/.local/bin/blend_bin/.associations', `${$('#inputAssociationBinaryName').val()}\0${$('#inputAssociationContainerName').val()}\n`, err => {
contents = require('js-yaml').dump(data) require('child_process').spawnSync('ln', ['-sf', $('#inputAssociationBinaryName').val() + '.' + $('#inputAssociationContainerName').val(), require('os').homedir() + '/.local/bin/blend_bin/' + $('#inputAssociationBinaryName').val()])
require('fs').writeFileSync(require('path').join(require('os').homedir(), '.config/blend/config.yaml'), contents, 'utf8') update_association_list()
} $('#inputAssociationContainerName').val('')
}); $('#inputAssociationBinaryName').val('')
e.addEventListener("dragstart", e => e.dataTransfer.setDragImage(new Image(), 0, 0), false);
}) })
} }
function remove_association(binary_name) {
require('child_process').spawnSync('bash', ['-c', `sed -i 's/^${binary_name}\\x0//g' ~/.local/bin/blend_bin/.associations`])
require('child_process').spawnSync('rm', ['-f', require('os').homedir() + '/.local/bin/blend_bin/' + binary_name])
update_association_list()
}
var binary_names = []
function update_association_list() {
require('fs').readFile(require('os').homedir() + '/.local/bin/blend_bin/.associations', 'utf8', (err, data) => {
let association_list_html = ''
binary_names = []
data.split('\n').forEach(line => {
if (line.includes('\0')) {
let binary_name = line.split('\0')[0]
binary_names.push(binary_name)
let container_name = line.split('\0')[1]
console.log(binary_name, container_name)
association_list_html += `
<div class="list-group-item" style="padding: 11px 20px 11px 20px; border: 0.5px solid rgba(255, 255, 255, 0.05);">
<div class="row align-items-center">
<div class="col">
<strong class="mb-0 container_name">${binary_name} <span style="padding-left: 20px; padding-right: 20px;">&rarr;</span> ${container_name}</strong>
</div>
<div class="col-auto">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-trash" viewBox="0 0 16 16" onclick="remove_association('${binary_name}')" style="cursor: pointer; z-index: 10;">
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
</svg>
</div>
</div>
</div>
`
}
})
if (association_list_html != '') {
$('#association-list').html(association_list_html)
} else {
$('#association-list').html(`
<div class="list-group-item">
<div class="row align-items-center">
<div class="col">
<strong class="mb-0">No associations.</strong>
<p class="text-muted mb-0">Add one from above. It's recommended to add associations for each of the supported package managers for easier usage (apt, pacman and dnf).</p>
</div>
</div>
</div>
`)
}
})
}
update_association_list()

View file

@ -1,7 +1,28 @@
<div class="container-fluid d-flex justify-content-center"> <div class="container-fluid d-flex justify-content-center">
<div class="col-12 col-lg-10 col-xl-8 mx-auto"> <div class="col-12 col-lg-10 col-xl-8 mx-auto">
<strong class="mb-0">Containers</strong> <strong class="mb-0">Containers</strong>
<p>You can install any app from any of the supported distributions (<b>Arch</b>, <b>Fedora</b>, and <b>Ubuntu</b>). Apps you install will appear as regular applications on your system (as well as binaries and package managers). You can override the priority in which common binaries are made available on the system by rearranging (dragging) the containers below to select the priority that should be assigned to each container.</p> <p>Installed apps will appear in the application launcher. Binaries can be executed with the container's name as a suffix. For example, <b>apt</b> -> <b>apt.ubuntu</b>, in a container named 'ubuntu'.</p>
<form onsubmit="create_container(); return false">
<div class="form-group row">
<div class="col-sm-4"></div>
<div class="col-sm-3">
<input type="text" class="form-control" id="inputContainerName" placeholder="Container name" required>
</div>
<div class="col-sm-4">
<select class="form-control" id="inputContainerDistro">
<option selected>Arch</option>
<option>Fedora Rawhide</option>
<option>Ubuntu 22.04</option>
<option>Ubuntu 22.10</option>
</select>
</div>
<div class="col-sm-1">
<button type="submit" class="btn btn-primary"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-plus" viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
</svg></button>
</div>
</div>
</form>
<div class="list-group mb-4 shadow" id="container-list"> <div class="list-group mb-4 shadow" id="container-list">
<div class="list-group-item"> <div class="list-group-item">
<div class="row align-items-center"> <div class="row align-items-center">
@ -17,29 +38,26 @@
<div class="container-fluid d-flex justify-content-center"> <div class="container-fluid d-flex justify-content-center">
<div class="col-12 col-lg-10 col-xl-8 mx-auto"> <div class="col-12 col-lg-10 col-xl-8 mx-auto">
<strong class="mb-0">Create new container</strong> <strong class="mb-0">Associations</strong>
<p>Create a container for each distribution to be able to use their package managers and other binaries directly from a terminal.</p> <p>You can associate a binary to a container so as to use it without a suffix.</p>
<form onsubmit="create_container(); return false"> <form onsubmit="create_association(); return false">
<div class="form-group row"> <div class="form-group row">
<label for="inputContainerName" class="col-sm-3 col-form-label">Container name</label> <div class="col-sm-4"></div>
<div class="col-sm-3">
<input type="text" class="form-control" id="inputAssociationBinaryName" placeholder="Binary name" required>
</div>
<div class="col-sm-4"> <div class="col-sm-4">
<input type="text" class="form-control" id="inputContainerName" placeholder="Container name" required> <input type="text" class="form-control" id="inputAssociationContainerName" placeholder="Container name" required>
</div>
<div class="col-sm-1">
<button type="submit" class="btn btn-primary"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" class="bi bi-plus" viewBox="0 0 16 16">
<path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
</svg></button>
</div> </div>
</div> </div>
<div class="form-group row">
<label for="inputContainerDistro" class="col-sm-3 col-form-label">Distribution</label>
<div class="col-sm-4">
<select class="form-control" id="inputContainerDistro">
<option selected>Arch</option>
<option>Fedora Rawhide</option>
<option>Ubuntu 22.04</option>
<option>Ubuntu 22.10</option>
</select>
</div>
</div>
<br>
<button type="submit" id="publish-button" class="btn btn-primary">Create container</button>
</form> </form>
<div class="list-group mb-4 shadow" id="association-list">
</div>
</div> </div>
</div> </div>

View file

@ -54,6 +54,7 @@
function create_term() { function create_term() {
ipc.removeAllListeners('terminal.reset') ipc.removeAllListeners('terminal.reset')
ipc.removeAllListeners('terminal.resize')
ipc.removeAllListeners('terminal.keystroke') ipc.removeAllListeners('terminal.keystroke')
ipc.removeAllListeners('terminal.incomingData') ipc.removeAllListeners('terminal.incomingData')
ipc.removeAllListeners('title') ipc.removeAllListeners('title')