Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Integrate the find-and-replace panel with the Julia Console #187

Merged
merged 8 commits into from
Jan 3, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions keymaps/ink.cson
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,14 @@
'.platform-win32 ink-terminal, .platform-linux ink-terminal':
'ctrl-shift-c': 'ink-terminal:copy'
'ctrl-shift-v': 'ink-terminal:paste'
'ctrl-shift-f': 'ink-terminal:show-search'

'.platform-darwin ink-terminal':
'cmd-c': 'ink-terminal:copy'
'cmd-v': 'ink-terminal:paste'
'cmd-f': 'ink-terminal:show-search'

'ink-terminal .search .searchinput atom-text-editor':
'enter': 'ink-terminal:find-next'
'shift-enter': 'ink-terminal:find-previous'
'escape': 'ink-terminal:close-search'
29 changes: 27 additions & 2 deletions lib/console2/console.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@ import { Terminal } from 'xterm'
import * as fit from 'xterm/lib/addons/fit/fit'
import * as webLinks from 'xterm/lib/addons/webLinks/webLinks'
import * as winptyCompat from 'xterm/lib/addons/winptyCompat/winptyCompat'
import * as search from 'xterm/lib/addons/search/search'
import TerminalElement from './view'
import PaneItem from '../util/pane-item'
import ResizeDetector from 'element-resize-detector'
import { debounce, throttle } from 'underscore-plus'
import { closest } from './helpers'
import { openExternal } from 'shell'
import SearchUI from './searchui'

let getTerminal = el => closest(el, 'ink-terminal').getModel()

Terminal.applyAddon(fit)
Terminal.applyAddon(webLinks)
Terminal.applyAddon(winptyCompat)
Terminal.applyAddon(search)

var subs

Expand All @@ -36,10 +39,30 @@ export default class InkTerminal extends PaneItem {
let term = getTerminal(target)
if (term != undefined) {
term.paste(process.platform != 'win32')
}},
'ink-terminal:show-search': ({target}) => {
let term = getTerminal(target)
if (term != undefined) {
term.searchui.show()
}},
'ink-terminal:find-next': ({target}) => {
let term = getTerminal(target)
if (term != undefined) {
term.searchui.find(true)
}},
'ink-terminal:find-previous': ({target}) => {
let term = getTerminal(target)
if (term != undefined) {
term.searchui.find(false)
}},
'ink-terminal:close-search': ({target}) => {
let term = getTerminal(target)
if (term != undefined) {
term.searchui.hide()
}}
}))

subs.add(atom.workspace.onDidStopChangingActivePaneItem((item) => {
subs.add(atom.workspace.onDidChangeActivePaneItem((item) => {
if (item instanceof InkTerminal) {
item.view.initialize(item)
item.terminal.focus()
Expand Down Expand Up @@ -92,6 +115,8 @@ export default class InkTerminal extends PaneItem {

this.view = new TerminalElement

this.searchui = new SearchUI(this.terminal)

etch.initialize(this)
etch.update(this).then(() => {
this.view.initialize(this)
Expand Down Expand Up @@ -215,7 +240,7 @@ export default class InkTerminal extends PaneItem {
bracketed && this.ty.write('\x1b[201~') // disable bracketed paste mode
}

show (view) {
show () {
this.terminal.focus()
}

Expand Down
168 changes: 168 additions & 0 deletions lib/console2/searchui.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
'use babel'
/** @jsx etch.dom */

import etch from 'etch'
import { Raw, Button, toView } from '../util/etch.js'
import { CompositeDisposable, Emitter, TextEditor } from 'atom'
import { Terminal } from 'xterm'
import * as fit from 'xterm/lib/addons/fit/fit'
import * as webLinks from 'xterm/lib/addons/webLinks/webLinks'
import * as winptyCompat from 'xterm/lib/addons/winptyCompat/winptyCompat'
import * as search from 'xterm/lib/addons/search/search'
import TerminalElement from './view'
import PaneItem from '../util/pane-item'
import ResizeDetector from 'element-resize-detector'
import { debounce, throttle } from 'underscore-plus'
import { closest } from './helpers'
import { openExternal } from 'shell'

export default class TerminalSearchUI {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: This class actually does the UI /and/ the search functionality. Would like SearchBar or SearchPanel or SearchBox be a reasonable name instead?

-- oh, wait, i guess "UI" doesn't necessarily mean "html-only"... Maybe ignore me. That said, when i first glanced through this PR i scrolled past this file expecting it just to be the HTML/CSS stuff, and expecting the functionality to be implemented somewhere else, so idk if others might have the same thought.

constructor (terminal) {
this.terminal = terminal
this.editor = new TextEditor( {mini: true, placeholderText: 'Find in Terminal'} )

this.useRegex = false
this.matchCase = false
this.wholeWord = false

this.initialized = false
this.errorMessage = ''

etch.initialize(this)
}

update () {}

toggleRegex () {
this.useRegex = !this.useRegex
this.refs.toggleRegex.element.classList.toggle('selected')
}

toggleCase () {
this.matchCase = !this.matchCase
this.refs.toggleCase.element.classList.toggle('selected')
}

toggleWhole () {
this.wholeWord = !this.wholeWord
this.refs.toggleWhole.element.classList.toggle('selected')
}

toggleError (show) {
let el = this.refs.errorMessage
show ? el.classList.remove('hidden') : el.classList.add('hidden')
etch.update(this)
}

find (next) {

let text = this.editor.getText()
if (this.useRegex) {
let msg = null
try {
new RegExp(text)
} catch (err) {
msg = err.message
}

if (msg !== null) {
this.errorMessage = msg
this.toggleError(true)
this.blinkRed()
return false
}
}
this.toggleError(false)

let found
if (next) {
found = this.terminal.findNext(text, {
regex: this.useRegex,
wholeWord: this.wholeWord,
caseSensitive: this.matchCase,
incremental: false
})
} else {
found = this.terminal.findPrevious(text, {
regex: this.useRegex,
wholeWord: this.wholeWord,
caseSensitive: this.matchCase
})
}

if (!found) this.blinkRed()
}

blinkRed () {
this.element.classList.add('nothingfound')
setTimeout(() => this.element.classList.remove('nothingfound'), 200)
}

render () {
return <div className='ink search hidden'>
<div className='inputs'>
<span className='searchinput'>{ toView(this.editor.element) }</span>
<div className='btn-group searchoptions'>
<Button className='btn-sm'
ref='toggleRegex'
alt='Use Regex'
onclick={() => this.toggleRegex()}>
.*
</Button>
<Button className='btn-sm'
ref='toggleCase'
alt='Match Case'
onclick={() => this.toggleCase()}>
Aa
</Button>
<Button className='btn-sm'
ref='toggleWhole'
alt='Whole Word'
onclick={() => this.toggleWhole()}>
\b
</Button>
</div>
<div className='btn-group nextprev'>
<Button className='btn-sm'
alt='Find Previous'
icon='chevron-left'
onclick={() => this.find(false)}>
</Button>
<Button className='btn-sm'
alt='Find Next'
icon='chevron-right'
onclick={() => this.find(true)}>
</Button>
</div>
<div className='btn-group closebutton'>
<Button className='btn-sm'
alt='Close'
icon='x'
onclick={() => this.hide()}>
</Button>
</div>
</div>
<div className='errormessage hidden'
ref='errorMessage'>
{this.errorMessage}
</div>
</div>
}

attach (element) {
if (!this.initialized) {
element.appendChild(this.element)
this.initialized = true
}
}

show () {
this.element.classList.remove('hidden')
this.editor.element.focus()
}

hide () {
this.element.classList.add('hidden')
this.terminal.focus()
}
}
2 changes: 2 additions & 0 deletions lib/console2/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class TerminalElement extends HTMLElement {
this.themeTerminal()
this.initMouseHandling()

this.model.searchui.attach(this)

return this
}

Expand Down
3 changes: 2 additions & 1 deletion lib/util/etch.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,9 @@ export class Badge extends Etch {
export class Button extends Etch {
render() {
let iconclass = this.props.icon ? ` icon icon-${this.props.icon}` : '';
let classname = this.props.className || ''
return <Tip alt={this.props.alt}>
<button className={'btn' + iconclass} disabled={this.props.disabled} onclick={this.props.onclick}>{
<button className={'btn' + iconclass + ' ' + classname} disabled={this.props.disabled} onclick={this.props.onclick}>{
this.children
}</button>
</Tip>;
Expand Down
6 changes: 3 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"katex": "^0.9.0",
"fs-extra": "^5.0.0",
"replace-in-file": "^3.0.0",
"xterm": "3.9.1",
"xterm": "3.10.0",
"chroma-js": "^1.3.7"
},
"scripts": {
Expand Down
39 changes: 38 additions & 1 deletion styles/terminal.less
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
@import "syntax-variables";

@import "ui-variables";

ink-terminal, .ink-terminal {
height: 100%;
Expand All @@ -14,6 +14,43 @@ ink-terminal, .ink-terminal {
background-color: @syntax-background-color !important;
}
}

.search {
position: absolute;
top: 0.5em;
right: 1em;
background-color: @app-background-color;
width: 30em;
padding: 0.5em;
z-index: 5;
transition: border-color 0.2s;
border: 2px @base-border-color solid;
border-radius: 2px;

.inputs {
flex-direction: row;
display: flex;

>* {
padding-left: 0.5em;
margin: auto;
}

.searchinput {
flex: 1;
padding-left: 0;
}
}

.errormessage {
color: @text-color-error;
margin-top: 0.5em;
}

&.nothingfound {
border-color: @background-color-error;
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, i'm really impressed how little code this took to add! Good job building up abstractions in this repo so reuse was so easy! :) I'm impressed! 😄

}

.scrollbars-visible-always {
Expand Down