-
Notifications
You must be signed in to change notification settings - Fork 37
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
Changes from all commits
6c006fe
ee9f33f
608d3a9
2aeef79
386e065
375b333
099d03b
141a74e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 { | ||
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() | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
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%; | ||
|
@@ -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; | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 { | ||
|
There was a problem hiding this comment.
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
orSearchPanel
orSearchBox
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.