Skip to content

Commit

Permalink
feat: Add commands to insert/run selected text (#23)
Browse files Browse the repository at this point in the history
Add command x-terminal:insert-selected-text
Add command x-terminal:run-selected-text 
Add `*` to active terminal title
Add setting to allow hidden terminals to stay active
  • Loading branch information
UziTech committed May 24, 2020
1 parent 856effd commit c10301a
Show file tree
Hide file tree
Showing 12 changed files with 501 additions and 112 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,21 @@ text editor or on a terminal.
Finally, terminal tabs are automatically reopened at the spot you placed them
when you last exited Atom.

## Active Terminal

The active terminal is the terminal that will be used when sending commands to
the terminal with commands like `x-terminal:insert-selected-text` and
`x-terminal:run-selected-text`

The active terminal will always have an astrix (`*`) in front of the title.
By default when a terminal is hidden it becomes inactive and the last used
visible terminal will become active. If there are no visible terminals none are
active.

The `Allow Hidden Terminal To Stay Active` setting will change the
default behavior and keep a terminal that is hidden active until another
terminal is focused.

## Organizing Terminals

To quickly organize your terminal tabs, simply use the main menu. You can also
Expand Down
12 changes: 9 additions & 3 deletions keymaps/x-terminal.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
"ctrl-alt-shift-right": "x-terminal:open-split-right",
"ctrl-alt-shift-i": "x-terminal:open-split-bottom-dock",
"ctrl-alt-shift-u": "x-terminal:open-split-left-dock",
"ctrl-alt-shift-o": "x-terminal:open-split-right-dock"
"ctrl-alt-shift-o": "x-terminal:open-split-right-dock",
"ctrl-alt-r": "x-terminal:run-selected-text",
"ctrl-alt-i": "x-terminal:insert-selected-text"
},
".platform-win32 atom-workspace": {
"ctrl-`": "x-terminal:open",
Expand All @@ -23,7 +25,9 @@
"ctrl-alt-shift-right": "x-terminal:open-split-right",
"ctrl-alt-shift-i": "x-terminal:open-split-bottom-dock",
"ctrl-alt-shift-u": "x-terminal:open-split-left-dock",
"ctrl-alt-shift-o": "x-terminal:open-split-right-dock"
"ctrl-alt-shift-o": "x-terminal:open-split-right-dock",
"ctrl-alt-r": "x-terminal:run-selected-text",
"ctrl-alt-i": "x-terminal:insert-selected-text"
},
".platform-darwin atom-workspace": {
"cmd-`": "x-terminal:open",
Expand All @@ -36,7 +40,9 @@
"cmd-alt-shift-right": "x-terminal:open-split-right",
"cmd-alt-shift-i": "x-terminal:open-split-bottom-dock",
"cmd-alt-shift-u": "x-terminal:open-split-left-dock",
"cmd-alt-shift-o": "x-terminal:open-split-right-dock"
"cmd-alt-shift-o": "x-terminal:open-split-right-dock",
"cmd-alt-r": "x-terminal:run-selected-text",
"cmd-alt-i": "x-terminal:insert-selected-text"
},
".platform-linux x-terminal": {
"ctrl-insert": "x-terminal:copy",
Expand Down
6 changes: 6 additions & 0 deletions spec/config-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,12 @@ describe('Call to colorBrightWhite()', () => {
})
})

describe('Call to allowHiddenToStayActive()', () => {
it('return false', () => {
expect(configDefaults.allowHiddenToStayActive).toBe(false)
})
})

describe('Call to leaveOpenAfterExit()', () => {
it('return true', () => {
expect(configDefaults.leaveOpenAfterExit).toBe(true)
Expand Down
2 changes: 2 additions & 0 deletions spec/element-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1787,7 +1787,9 @@ describe('XTerminalElement', () => {

it('focusOnTerminal()', () => {
spyOn(this.element.terminal, 'focus')
spyOn(this.element.model, 'setActive')
this.element.focusOnTerminal()
expect(this.element.model.setActive).toHaveBeenCalled()
expect(this.element.terminal.focus).toHaveBeenCalled()
})

Expand Down
112 changes: 106 additions & 6 deletions spec/model-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@ describe('XTerminalModel', () => {
expect(this.model.getTitle()).toBe(expected)
})

it('getTitle() when active', () => {
spyOn(this.model, 'isActiveTerminal').and.returnValue(true)
expect(this.model.getTitle()).toBe('* X Terminal')
})

it('getElement()', () => {
const expected = { somekey: 'somevalue' }
this.model.element = expected
Expand Down Expand Up @@ -472,17 +477,112 @@ describe('XTerminalModel', () => {
expect(this.model.element.ptyProcess.write.calls.allArgs()).toEqual([[expectedText]])
})

it('setNewPane(event)', async () => {
it('setActive()', async function () {
const pane = atom.workspace.getCenter().getActivePane()
const uri = 'x-terminal://somesessionid/'
const terminalsSet = new Set()
const model = new XTerminalModel({
const model1 = new XTerminalModel({
uri: uri,
terminals_set: terminalsSet,
})
await model.initializedPromise
const expected = {}
model.setNewPane(expected)
expect(model.pane).toBe(expected)
await model1.initializedPromise
pane.addItem(model1)
model1.setNewPane(pane)
const model2 = new XTerminalModel({
uri: uri,
terminals_set: terminalsSet,
})
await model2.initializedPromise
pane.addItem(model2)
model2.setNewPane(pane)
expect(model1.activeIndex).toBe(0)
expect(model2.activeIndex).toBe(1)
model2.setActive()
expect(model1.activeIndex).toBe(1)
expect(model2.activeIndex).toBe(0)
})

describe('setNewPane', () => {
it('(mock)', async () => {
const expected = { getContainer: () => ({ getLocation: () => {} }) }
this.model.setNewPane(expected)
expect(this.model.pane).toBe(expected)
expect(this.model.dock).toBe(null)
})

it('(center)', async () => {
const pane = atom.workspace.getCenter().getActivePane()
this.model.setNewPane(pane)
expect(this.model.pane).toBe(pane)
expect(this.model.dock).toBe(null)
})

it('(left)', async () => {
const dock = atom.workspace.getLeftDock()
const pane = dock.getActivePane()
this.model.setNewPane(pane)
expect(this.model.pane).toBe(pane)
expect(this.model.dock).toBe(dock)
})

it('(right)', async () => {
const dock = atom.workspace.getRightDock()
const pane = dock.getActivePane()
this.model.setNewPane(pane)
expect(this.model.pane).toBe(pane)
expect(this.model.dock).toBe(dock)
})

it('(bottom)', async () => {
const dock = atom.workspace.getBottomDock()
const pane = dock.getActivePane()
this.model.setNewPane(pane)
expect(this.model.pane).toBe(pane)
expect(this.model.dock).toBe(dock)
})
})

it('isVisible() in pane', () => {
const pane = atom.workspace.getCenter().getActivePane()
this.model.setNewPane(pane)
expect(this.model.isVisible()).toBe(false)
pane.setActiveItem(this.model)
expect(this.model.isVisible()).toBe(true)
})

it('isVisible() in dock', () => {
const dock = atom.workspace.getBottomDock()
const pane = dock.getActivePane()
this.model.setNewPane(pane)
pane.setActiveItem(this.model)
expect(this.model.isVisible()).toBe(false)
dock.show()
expect(this.model.isVisible()).toBe(true)
})

it('isActiveTerminal() visible and active', () => {
this.model.activeIndex = 0
spyOn(this.model, 'isVisible').and.returnValue(true)
expect(this.model.isActiveTerminal()).toBe(true)
})

it('isActiveTerminal() visible and not active', () => {
this.model.activeIndex = 1
spyOn(this.model, 'isVisible').and.returnValue(true)
expect(this.model.isActiveTerminal()).toBe(false)
})

it('isActiveTerminal() invisible and active', () => {
this.model.activeIndex = 0
spyOn(this.model, 'isVisible').and.returnValue(false)
expect(this.model.isActiveTerminal()).toBe(false)
})

it('isActiveTerminal() allowHiddenToStayActive', () => {
atom.config.set('x-terminal.terminalSettings.allowHiddenToStayActive', true)
this.model.activeIndex = 0
spyOn(this.model, 'isVisible').and.returnValue(false)
expect(this.model.isActiveTerminal()).toBe(true)
})

it('toggleProfileMenu()', () => {
Expand Down
63 changes: 63 additions & 0 deletions spec/utils-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,67 @@ describe('Utilities', () => {
expect(hLine.classList.contains('x-terminal-profile-menu-element-hline')).toBe(true)
expect(hLine.textContent).toBe('.')
})

describe('recalculateActive()', () => {
const createTerminals = (num = 1) => {
const terminals = []
for (let i = 0; i < num; i++) {
terminals.push({
activeIndex: i,
isVisible () {},
emitter: {
emit () {},
},
})
}
return terminals
}

it('active first', () => {
const terminals = createTerminals(2)
const terminalsSet = new Set(terminals)
utils.recalculateActive(terminalsSet, terminals[1])
expect(terminals[0].activeIndex).toBe(1)
expect(terminals[1].activeIndex).toBe(0)
})

it('visible before hidden', () => {
const terminals = createTerminals(2)
const terminalsSet = new Set(terminals)
spyOn(terminals[1], 'isVisible').and.returnValue(true)
utils.recalculateActive(terminalsSet)
expect(terminals[0].activeIndex).toBe(1)
expect(terminals[1].activeIndex).toBe(0)
})

it('allowHiddenToStayActive', () => {
atom.config.set('x-terminal.terminalSettings.allowHiddenToStayActive', true)
const terminals = createTerminals(2)
const terminalsSet = new Set(terminals)
spyOn(terminals[1], 'isVisible').and.returnValue(true)
utils.recalculateActive(terminalsSet)
expect(terminals[0].activeIndex).toBe(0)
expect(terminals[1].activeIndex).toBe(1)
})

it('lower active index first', () => {
const terminals = createTerminals(2)
const terminalsSet = new Set(terminals)
terminals[0].activeIndex = 1
terminals[1].activeIndex = 0
utils.recalculateActive(terminalsSet)
expect(terminals[0].activeIndex).toBe(1)
expect(terminals[1].activeIndex).toBe(0)
})

it('emit did-change-title', () => {
const terminals = createTerminals(2)
const terminalsSet = new Set(terminals)
spyOn(terminals[0].emitter, 'emit')
spyOn(terminals[1].emitter, 'emit')
utils.recalculateActive(terminalsSet)
expect(terminals[0].emitter.emit).toHaveBeenCalledWith('did-change-title')
expect(terminals[1].emitter.emit).toHaveBeenCalledWith('did-change-title')
})
})
})
48 changes: 48 additions & 0 deletions spec/x-terminal-spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/** @babel */

import * as xTerminal from '../src/x-terminal'

const xTerminalInstance = xTerminal.getInstance()

describe('x-terminal', () => {
describe('getSelectedText()', () => {
it('returns selection', () => {
spyOn(atom.workspace, 'getActiveTextEditor').and.returnValue({
getSelectedText () {
return 'selection'
},
})
const selection = xTerminalInstance.getSelectedText()
expect(selection).toBe('selection')
})

it('returns removes newlines at the end', () => {
spyOn(atom.workspace, 'getActiveTextEditor').and.returnValue({
getSelectedText () {
return 'line1\r\nline2\r\n'
},
})
const selection = xTerminalInstance.getSelectedText()
expect(selection).toBe('line1\r\nline2')
})

it('returns entire line if nothing selected and moves down', () => {
const moveDown = jasmine.createSpy('moveDown')
spyOn(atom.workspace, 'getActiveTextEditor').and.returnValue({
getSelectedText () {
return ''
},
getCursorBufferPosition () {
return { row: 1, column: 1 }
},
lineTextForBufferRow (row) {
return `line${row}`
},
moveDown,
})
const selection = xTerminalInstance.getSelectedText()
expect(selection).toBe('line1')
expect(moveDown).toHaveBeenCalledWith(1)
})
})
})
7 changes: 7 additions & 0 deletions src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export function resetConfigDefaults () {
colorBrightMagenta: '#ad7fa8',
colorBrightCyan: '#34e2e2',
colorBrightWhite: '#eeeeec',
allowHiddenToStayActive: false,
leaveOpenAfterExit: true,
allowRelaunchingTerminalsOnStartup: true,
relaunchTerminalOnStartup: true,
Expand Down Expand Up @@ -384,6 +385,12 @@ export const config = configOrder({
toMenuSetting: (val) => val,
},
},
allowHiddenToStayActive: {
title: 'Allow Hidden Terminal To Stay Active',
description: 'When an active terminal is hidden keep it active until another terminal is focused.',
type: 'boolean',
default: configDefaults.allowHiddenToStayActive,
},
leaveOpenAfterExit: {
title: 'Leave Open After Exit',
description: 'Whether to leave terminal emulators open after their shell processes have exited.',
Expand Down
1 change: 1 addition & 0 deletions src/element.js
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,7 @@ class XTerminalElementImpl extends HTMLElement {

focusOnTerminal () {
if (this.terminal) {
this.model.setActive()
this.terminal.focus()
}
}
Expand Down
Loading

0 comments on commit c10301a

Please sign in to comment.