mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-09-20 15:37:46 +03:00
Merge remote-tracking branch 'origin/master' into status-bar-buffer-modified-indicator
This commit is contained in:
commit
09024e0dc8
@ -6,4 +6,5 @@ requireExtension 'command-panel'
|
||||
requireExtension 'keybindings-view'
|
||||
requireExtension 'snippets'
|
||||
requireExtension 'status-bar'
|
||||
|
||||
requireExtension 'wrap-guide'
|
||||
requireExtension 'markdown-preview'
|
||||
|
3
.github
Normal file
3
.github
Normal file
@ -0,0 +1,3 @@
|
||||
[docs]
|
||||
title = The Guide to Atom
|
||||
manifest = intro.md, styling.md, extensions/intro.md, extensions/markdown-preview.md, extensions/wrap-guide.md
|
1
.pairs
1
.pairs
@ -2,6 +2,7 @@ pairs:
|
||||
ns: Nathan Sobo; nathan
|
||||
cj: Corey Johnson; cj
|
||||
dg: David Graham; dgraham
|
||||
ks: Kevin Sawicki; kevin
|
||||
email:
|
||||
domain: github.com
|
||||
#global: true
|
||||
|
1
docs/extensions/intro.md
Normal file
1
docs/extensions/intro.md
Normal file
@ -0,0 +1 @@
|
||||
## Extensions
|
7
docs/extensions/markdown-preview.md
Normal file
7
docs/extensions/markdown-preview.md
Normal file
@ -0,0 +1,7 @@
|
||||
### Markdown Preview
|
||||
|
||||
The `markdown-preview` extension displays the rendered HTML for the markdown
|
||||
in the current editor.
|
||||
|
||||
It can be activated from the editor using the `meta-P` key-binding and is
|
||||
currently enabled for `.md` and `.markdown` files.
|
31
docs/extensions/wrap-guide.md
Normal file
31
docs/extensions/wrap-guide.md
Normal file
@ -0,0 +1,31 @@
|
||||
### Wrap Guide
|
||||
|
||||
The `wrap-guide` extension places a vertical line in each editor at a certain
|
||||
column to guide your formatting so lines do not exceed a certain width.
|
||||
|
||||
By default the wrap-guide is placed at the 80th column.
|
||||
|
||||
#### Configuration
|
||||
|
||||
You can configure where this column is on a per-path basis using the following
|
||||
configuration data options:
|
||||
|
||||
```coffeescript
|
||||
wrapGuideConfig =
|
||||
getGuideColumn: (path, defaultColumn) ->
|
||||
if path.indexOf('.mm', path.length - 3) is -1
|
||||
return defaultColumn
|
||||
else
|
||||
return -1 # Disable the guide for Objective-C files
|
||||
requireExtension 'wrap-guide', wrapGuideConfig
|
||||
```
|
||||
|
||||
You can configure the color and/or width of the line by adding the following
|
||||
CSS to a custom stylesheet:
|
||||
|
||||
```css
|
||||
.wrap-guide {
|
||||
width: 10px;
|
||||
background-color: red;
|
||||
}
|
||||
```
|
@ -1,64 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
background: blue;
|
||||
}
|
||||
|
||||
#flexbox-container {
|
||||
background: black;
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
height: 200px;
|
||||
width: 400px;
|
||||
display: -webkit-flex;
|
||||
-webkit-flex-direction: row;
|
||||
overflow: hidden;
|
||||
border: 1px solid navy;
|
||||
-webkit-align-items: stretch;
|
||||
}
|
||||
|
||||
#flexbox-item-1 {
|
||||
background: green;
|
||||
overflow: auto;
|
||||
-webkit-flex: 1;
|
||||
}
|
||||
|
||||
#flexbox-item-2 {
|
||||
overflow: scroll;
|
||||
background: orange;
|
||||
-webkit-flex: 1;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="flexbox-container">
|
||||
<div id="flexbox-item-1">
|
||||
<div id="flexbox-item-1-content">
|
||||
My cross size (height) should be equal to the height of my flexbox container. I should overflow, because my height should be too short to contain all my content.
|
||||
<div>1</div>
|
||||
<div>2</div>
|
||||
<div>3</div>
|
||||
<div>4</div>
|
||||
<div>5</div>
|
||||
<div>6</div>
|
||||
<div>7</div>
|
||||
<div>8</div>
|
||||
<div>9</div>
|
||||
<div>10</div>
|
||||
<div>11</div>
|
||||
<div>12</div>
|
||||
<div>13</div>
|
||||
<div>14</div>
|
||||
<div>15</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="flexbox-item-2">
|
||||
My cross size (height) should also be equal to the height of my flexbox container, but I don't overflow.
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -1,84 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>wtf</title>
|
||||
<link href="static/reset.css" rel="stylesheet">
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: black;
|
||||
display: -webkit-box;
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
}
|
||||
|
||||
.row {
|
||||
background-color: green;
|
||||
display: -webkit-box;
|
||||
-webkit-box-flex: 1;
|
||||
-webkit-box-orient: horizontal;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.column {
|
||||
background-color: red;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-box-flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.top {
|
||||
background-color: orange;
|
||||
height: 200px;
|
||||
}
|
||||
|
||||
.left {
|
||||
background-color: purple;
|
||||
width: 100px;
|
||||
}
|
||||
|
||||
.middle {
|
||||
background-color: blue;
|
||||
display: -webkit-box;
|
||||
-webkit-box-flex: 1;
|
||||
}
|
||||
|
||||
.right {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
.i {
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.full-height-child {
|
||||
background: black;
|
||||
color: white;
|
||||
display: -webkit-box;
|
||||
-webkit-box-flex: 1;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class='column'>
|
||||
<div class='i top'>Keffiyeh mustache pickled post-ironic, lomo vegan food truck helvetica direct trade nostrud. Assumenda odio brunch, DIY non anim delectus sunt aliqua organic VHS nihil pork belly accusamus. Bushwick vice high life tumblr mumblecore ullamco. High life pop-up lomo, pariatur exercitation odio helvetica food truck ex williamsburg stumptown hoodie ea polaroid jean shorts. Keytar sed sapiente, mumblecore fixie +1 cred occaecat accusamus. Fanny pack authentic dolor, id four loko dolore ex +1 pop-up. Thundercats cliche aliqua, fugiat irony marfa chambray banksy kogi organic selvage VHS DIY. Id mumblecore nisi, brunch narwhal nostrud vegan squid before they sold out. Sriracha laborum nesciunt, in salvia you probably haven't heard of them mustache VHS commodo squid proident williamsburg. Magna vero gentrify labore, non american apparel occaecat put a bird on it mlkshk DIY occupy eu pinterest aute cliche. Nihil delectus commodo voluptate nostrud. Tattooed tempor skateboard, sed tumblr nostrud chambray put a bird on it non salvia helvetica consectetur mcsweeney's incididunt. Est semiotics ut yr, fanny pack leggings voluptate carles. Ea odd future hoodie cred. Ex small batch wayfarers sartorial. Delectus mumblecore skateboard, kogi esse keytar vinyl sriracha before they sold out typewriter marfa odd future viral mollit. Polaroid biodiesel street art viral cupidatat art party, post-ironic minim. Irony qui reprehenderit, put a bird on it eiusmod iphone labore skateboard. Craft beer keffiyeh echo park, 3 wolf moon thundercats gentrify dolor beard VHS ullamco cillum post-ironic qui chambray. Sartorial cred ex, aliqua trust fund est consectetur put a bird on it in nisi cupidatat sapiente art party freegan. Mlkshk authentic velit laborum. Est tattooed hella pickled qui flexitarian. Mustache wes anderson food truck, cardigan selvage organic wayfarers VHS irure typewriter irony. Kale chips pitchfork four loko before they sold out. Quis blog proident jean shorts voluptate, photo booth high life post-ironic odio hella whatever. Vinyl 3 wolf moon qui, officia non artisan et helvetica cosby sweater velit street art proident quinoa reprehenderit. Odd future fap put a bird on it laboris, kale chips tempor duis velit. Voluptate mlkshk brooklyn nihil. Hoodie sustainable excepteur next level. Anim qui aliqua officia keffiyeh semiotics. Est brooklyn pop-up photo booth, jean shorts banksy mumblecore. Consequat typewriter ennui put a bird on it odio. Reprehenderit narwhal master cleanse, messenger bag sed wayfarers vinyl adipisicing ex nesciunt. Mollit carles ethnic craft beer shoreditch, incididunt veniam laboris small batch authentic dreamcatcher proident you probably haven't heard of them seitan. Id art party narwhal assumenda farm-to-table brooklyn. Seitan artisan adipisicing put a bird on it aute lomo. Next level letterpress pitchfork, master cleanse Austin small batch scenester mlkshk trust fund hella accusamus laboris iphone lo-fi. Minim consectetur fanny pack occupy, lo-fi twee cupidatat nostrud laborum sint. Master cleanse consectetur excepteur enim food truck banksy. Qui nisi truffaut helvetica excepteur. Quinoa banksy non four loko tattooed keffiyeh pickled, ex semiotics quis odd future consectetur flexitarian. Quis readymade 8-bit nisi. </div>
|
||||
<div class='row'>
|
||||
<div class='i left'>Keffiyeh mustache pickled post-ironic, lomo vegan food truck helvetica direct trade nostrud. Assumenda odio brunch, DIY non anim delectus sunt aliqua organic VHS nihil pork belly accusamus. Bushwick vice high life tumblr mumblecore ullamco. High life pop-up lomo, pariatur exercitation odio helvetica food truck ex williamsburg stumptown hoodie ea polaroid jean shorts. Keytar sed sapiente, mumblecore fixie +1 cred occaecat accusamus. Fanny pack authentic dolor, id four loko dolore ex +1 pop-up. Thundercats cliche aliqua, fugiat irony marfa chambray banksy kogi organic selvage VHS DIY. Id mumblecore nisi, brunch narwhal nostrud vegan squid before they sold out. Sriracha laborum nesciunt, in salvia you probably haven't heard of them mustache VHS commodo squid proident williamsburg. Magna vero gentrify labore, non american apparel occaecat put a bird on it mlkshk DIY occupy eu pinterest aute cliche. Nihil delectus commodo voluptate nostrud. Tattooed tempor skateboard, sed tumblr nostrud chambray put a bird on it non salvia helvetica consectetur mcsweeney's incididunt. Est semiotics ut yr, fanny pack leggings voluptate carles. Ea odd future hoodie cred. Ex small batch wayfarers sartorial. Delectus mumblecore skateboard, kogi esse keytar vinyl sriracha before they sold out typewriter marfa odd future viral mollit. Polaroid biodiesel street art viral cupidatat art party, post-ironic minim. Irony qui reprehenderit, put a bird on it eiusmod iphone labore skateboard. Craft beer keffiyeh echo park, 3 wolf moon thundercats gentrify dolor beard VHS ullamco cillum post-ironic qui chambray. Sartorial cred ex, aliqua trust fund est consectetur put a bird on it in nisi cupidatat sapiente art party freegan. Mlkshk authentic velit laborum. Est tattooed hella pickled qui flexitarian. Mustache wes anderson food truck, cardigan selvage organic wayfarers VHS irure typewriter irony. Kale chips pitchfork four loko before they sold out. Quis blog proident jean shorts voluptate, photo booth high life post-ironic odio hella whatever. Vinyl 3 wolf moon qui, officia non artisan et helvetica cosby sweater velit street art proident quinoa reprehenderit. Odd future fap put a bird on it laboris, kale chips tempor duis velit. Voluptate mlkshk brooklyn nihil. Hoodie sustainable excepteur next level. Anim qui aliqua officia keffiyeh semiotics. Est brooklyn pop-up photo booth, jean shorts banksy mumblecore. Consequat typewriter ennui put a bird on it odio. Reprehenderit narwhal master cleanse, messenger bag sed wayfarers vinyl adipisicing ex nesciunt. Mollit carles ethnic craft beer shoreditch, incididunt veniam laboris small batch authentic dreamcatcher proident you probably haven't heard of them seitan. Id art party narwhal assumenda farm-to-table brooklyn. Seitan artisan adipisicing put a bird on it aute lomo. Next level letterpress pitchfork, master cleanse Austin small batch scenester mlkshk trust fund hella accusamus laboris iphone lo-fi. Minim consectetur fanny pack occupy, lo-fi twee cupidatat nostrud laborum sint. Master cleanse consectetur excepteur enim food truck banksy. Qui nisi truffaut helvetica excepteur. Quinoa banksy non four loko tattooed keffiyeh pickled, ex semiotics quis odd future consectetur flexitarian. Quis readymade 8-bit nisi. </div>
|
||||
<div class='i middle'>
|
||||
<div class="full-height-child">
|
||||
I am a child of a flexbox item. My height should be exactly the height of my container.
|
||||
</div>
|
||||
</div>
|
||||
<div class='i right'>Keffiyeh mustache pickled post-ironic, lomo vegan food truck helvetica direct trade nostrud. Assumenda odio brunch, DIY non anim delectus sunt aliqua organic VHS nihil pork belly accusamus. Bushwick vice high life tumblr mumblecore ullamco. High life pop-up lomo, pariatur exercitation odio helvetica food truck ex williamsburg stumptown hoodie ea polaroid jean shorts. Keytar sed sapiente, mumblecore fixie +1 cred occaecat accusamus. Fanny pack authentic dolor, id four loko dolore ex +1 pop-up. Thundercats cliche aliqua, fugiat irony marfa chambray banksy kogi organic selvage VHS DIY. Id mumblecore nisi, brunch narwhal nostrud vegan squid before they sold out. Sriracha laborum nesciunt, in salvia you probably haven't heard of them mustache VHS commodo squid proident williamsburg. Magna vero gentrify labore, non american apparel occaecat put a bird on it mlkshk DIY occupy eu pinterest aute cliche. Nihil delectus commodo voluptate nostrud. Tattooed tempor skateboard, sed tumblr nostrud chambray put a bird on it non salvia helvetica consectetur mcsweeney's incididunt. Est semiotics ut yr, fanny pack leggings voluptate carles. Ea odd future hoodie cred. Ex small batch wayfarers sartorial. Delectus mumblecore skateboard, kogi esse keytar vinyl sriracha before they sold out typewriter marfa odd future viral mollit. Polaroid biodiesel street art viral cupidatat art party, post-ironic minim. Irony qui reprehenderit, put a bird on it eiusmod iphone labore skateboard. Craft beer keffiyeh echo park, 3 wolf moon thundercats gentrify dolor beard VHS ullamco cillum post-ironic qui chambray. Sartorial cred ex, aliqua trust fund est consectetur put a bird on it in nisi cupidatat sapiente art party freegan. Mlkshk authentic velit laborum. Est tattooed hella pickled qui flexitarian. Mustache wes anderson food truck, cardigan selvage organic wayfarers VHS irure typewriter irony. Kale chips pitchfork four loko before they sold out. Quis blog proident jean shorts voluptate, photo booth high life post-ironic odio hella whatever. Vinyl 3 wolf moon qui, officia non artisan et helvetica cosby sweater velit street art proident quinoa reprehenderit. Odd future fap put a bird on it laboris, kale chips tempor duis velit. Voluptate mlkshk brooklyn nihil. Hoodie sustainable excepteur next level. Anim qui aliqua officia keffiyeh semiotics. Est brooklyn pop-up photo booth, jean shorts banksy mumblecore. Consequat typewriter ennui put a bird on it odio. Reprehenderit narwhal master cleanse, messenger bag sed wayfarers vinyl adipisicing ex nesciunt. Mollit carles ethnic craft beer shoreditch, incididunt veniam laboris small batch authentic dreamcatcher proident you probably haven't heard of them seitan. Id art party narwhal assumenda farm-to-table brooklyn. Seitan artisan adipisicing put a bird on it aute lomo. Next level letterpress pitchfork, master cleanse Austin small batch scenester mlkshk trust fund hella accusamus laboris iphone lo-fi. Minim consectetur fanny pack occupy, lo-fi twee cupidatat nostrud laborum sint. Master cleanse consectetur excepteur enim food truck banksy. Qui nisi truffaut helvetica excepteur. Quinoa banksy non four loko tattooed keffiyeh pickled, ex semiotics quis odd future consectetur flexitarian. Quis readymade 8-bit nisi. </div>
|
||||
</div>
|
||||
<div class='i bottom'>Keffiyeh mustache pickled post-ironic, lomo vegan food truck helvetica direct trade nostrud. Assumenda odio brunch, DIY non anim delectus sunt aliqua organic VHS nihil pork belly accusamus. Bushwick vice high life tumblr mumblecore ullamco. High life pop-up lomo, pariatur exercitation odio helvetica food truck ex williamsburg stumptown hoodie ea polaroid jean shorts. Keytar sed sapiente, mumblecore fixie +1 cred occaecat accusamus. Fanny pack authentic dolor, id four loko dolore ex +1 pop-up. Thundercats cliche aliqua, fugiat irony marfa chambray banksy kogi organic selvage VHS DIY. Id mumblecore nisi, brunch narwhal nostrud vegan squid before they sold out. Sriracha laborum nesciunt, in salvia you probably haven't heard of them mustache VHS commodo squid proident williamsburg. Magna vero gentrify labore, non american apparel occaecat put a bird on it mlkshk DIY occupy eu pinterest aute cliche. Nihil delectus commodo voluptate nostrud. Tattooed tempor skateboard, sed tumblr nostrud chambray put a bird on it non salvia helvetica consectetur mcsweeney's incididunt. Est semiotics ut yr, fanny pack leggings voluptate carles. Ea odd future hoodie cred. Ex small batch wayfarers sartorial. Delectus mumblecore skateboard, kogi esse keytar vinyl sriracha before they sold out typewriter marfa odd future viral mollit. Polaroid biodiesel street art viral cupidatat art party, post-ironic minim. Irony qui reprehenderit, put a bird on it eiusmod iphone labore skateboard. Craft beer keffiyeh echo park, 3 wolf moon thundercats gentrify dolor beard VHS ullamco cillum post-ironic qui chambray. Sartorial cred ex, aliqua trust fund est consectetur put a bird on it in nisi cupidatat sapiente art party freegan. Mlkshk authentic velit laborum. Est tattooed hella pickled qui flexitarian. Mustache wes anderson food truck, cardigan selvage organic wayfarers VHS irure typewriter irony. Kale chips pitchfork four loko before they sold out. Quis blog proident jean shorts voluptate, photo booth high life post-ironic odio hella whatever. Vinyl 3 wolf moon qui, officia non artisan et helvetica cosby sweater velit street art proident quinoa reprehenderit. Odd future fap put a bird on it laboris, kale chips tempor duis velit. Voluptate mlkshk brooklyn nihil. Hoodie sustainable excepteur next level. Anim qui aliqua officia keffiyeh semiotics. Est brooklyn pop-up photo booth, jean shorts banksy mumblecore. Consequat typewriter ennui put a bird on it odio. Reprehenderit narwhal master cleanse, messenger bag sed wayfarers vinyl adipisicing ex nesciunt. Mollit carles ethnic craft beer shoreditch, incididunt veniam laboris small batch authentic dreamcatcher proident you probably haven't heard of them seitan. Id art party narwhal assumenda farm-to-table brooklyn. Seitan artisan adipisicing put a bird on it aute lomo. Next level letterpress pitchfork, master cleanse Austin small batch scenester mlkshk trust fund hella accusamus laboris iphone lo-fi. Minim consectetur fanny pack occupy, lo-fi twee cupidatat nostrud laborum sint. Master cleanse consectetur excepteur enim food truck banksy. Qui nisi truffaut helvetica excepteur. Quinoa banksy non four loko tattooed keffiyeh pickled, ex semiotics quis odd future consectetur flexitarian. Quis readymade 8-bit nisi. </div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,53 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
background: blue;
|
||||
}
|
||||
|
||||
#flexbox-container {
|
||||
background: black;
|
||||
position: absolute;*
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
height: 200px;
|
||||
width: 200px;
|
||||
display: -webkit-flex;
|
||||
-webkit-flex-direction: column;
|
||||
overflow: hidden;
|
||||
border: 1px solid navy;
|
||||
}
|
||||
|
||||
#flexbox-item-1 {
|
||||
background: green;
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
-webkit-flex: 1 0 100%;
|
||||
}
|
||||
|
||||
#flexbox-item-1-content {
|
||||
width: -webkit-fill-available;
|
||||
min-height: -webkit-fill-available;
|
||||
height: -webkit-fill-available;
|
||||
background: purple;
|
||||
}
|
||||
|
||||
#flexbox-item-2 {
|
||||
background: orange;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="flexbox-container">
|
||||
<div id="flexbox-item-1">
|
||||
<div id="flexbox-item-1-content">
|
||||
I should be 100% of the height of my container, right?
|
||||
</div>
|
||||
</div>
|
||||
<div id="flexbox-item-2">
|
||||
I don't have a flex property, so I should have an auto height
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
3
docs/intro.md
Normal file
3
docs/intro.md
Normal file
@ -0,0 +1,3 @@
|
||||
## The Definitive Guide to Atom
|
||||
|
||||
Welcome!
|
24
docs/styling.md
Normal file
24
docs/styling.md
Normal file
@ -0,0 +1,24 @@
|
||||
## Styling Tweaks
|
||||
|
||||
### Cursor Line Highlighting
|
||||
|
||||
Atom highlights the background color of the entire line where the cursor
|
||||
currently is and also changes the foreground color of the line number in the
|
||||
gutter.
|
||||
|
||||
You can change the background color using the following CSS:
|
||||
|
||||
```css
|
||||
.editor.focused .line.cursor-line,
|
||||
.editor.focused .line-number.cursor-line-number-background {
|
||||
background-color: green;
|
||||
}
|
||||
```
|
||||
|
||||
You can change the line number foreground color using the following CSS:
|
||||
|
||||
```css
|
||||
.editor.focused .line-number.cursor-line-number {
|
||||
color: blue;
|
||||
}
|
||||
```
|
6
notes/kyles-little-things.md
Normal file
6
notes/kyles-little-things.md
Normal file
@ -0,0 +1,6 @@
|
||||
## The Little Things™
|
||||
I recently switched over to Sublime Text 2 and for the most part it's been pretty awesome. But I've been noticing a lot of little things that I really appreciate in an editor, so I thought I'd note them down.
|
||||
|
||||
1. Indenting soft-wrapped lines http://share.kyleneath.com/captures/_upsell.html.erb-20120127-231402.png
|
||||
2. Respecting Chrome-like tab behavior (drag between windows/panes, `⌘+Shift+T` to get last closed tab back, `⌘+N` for a new tab in your current pane)
|
||||
3. Indent markers http://share.kyleneath.com/captures/billing_dependency.rb-20120127-232754.png
|
@ -1360,6 +1360,19 @@ describe "EditSession", ->
|
||||
editSession.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(4)).toBe " while(items.length > 0) {"
|
||||
|
||||
it "uncomments when the line lacks the trailing whitespace in the comment regex", ->
|
||||
editSession.setSelectedBufferRange([[10, 0], [10, 0]])
|
||||
editSession.toggleLineCommentsInSelection()
|
||||
|
||||
expect(buffer.lineForRow(10)).toBe "// "
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[10, 3], [10, 3]]
|
||||
editSession.backspace()
|
||||
expect(buffer.lineForRow(10)).toBe "//"
|
||||
|
||||
editSession.toggleLineCommentsInSelection()
|
||||
expect(buffer.lineForRow(10)).toBe ""
|
||||
expect(editSession.getSelectedBufferRange()).toEqual [[10, 0], [10, 0]]
|
||||
|
||||
describe ".undo() and .redo()", ->
|
||||
it "undoes/redoes the last change", ->
|
||||
editSession.insertText("foo")
|
||||
|
@ -157,7 +157,7 @@ describe "Editor", ->
|
||||
editSession = editor.activeEditSession
|
||||
spyOn(editSession, 'destroy').andCallThrough()
|
||||
spyOn(editor, "remove").andCallThrough()
|
||||
editor.trigger "close"
|
||||
editor.trigger "core:close"
|
||||
expect(editSession.destroy).toHaveBeenCalled()
|
||||
expect(editor.remove).not.toHaveBeenCalled()
|
||||
expect(editor.getBuffer()).toBe buffer
|
||||
@ -167,13 +167,13 @@ describe "Editor", ->
|
||||
expect(editor.mini).toBeFalsy()
|
||||
expect(editor.editSessions.length).toBe 1
|
||||
spyOn(editor, 'remove').andCallThrough()
|
||||
editor.trigger 'close'
|
||||
editor.trigger 'core:close'
|
||||
spyOn(editSession, 'destroy').andCallThrough()
|
||||
expect(editor.remove).toHaveBeenCalled()
|
||||
|
||||
miniEditor = new Editor(mini: true)
|
||||
spyOn(miniEditor, 'remove').andCallThrough()
|
||||
miniEditor.trigger 'close'
|
||||
miniEditor.trigger 'core:close'
|
||||
expect(miniEditor.remove).not.toHaveBeenCalled()
|
||||
|
||||
describe "when buffer is modified", ->
|
||||
@ -181,7 +181,7 @@ describe "Editor", ->
|
||||
spyOn(editor, 'remove').andCallThrough()
|
||||
spyOn(atom, 'confirm')
|
||||
editor.insertText("I AM CHANGED!")
|
||||
editor.trigger "close"
|
||||
editor.trigger "core:close"
|
||||
expect(editor.remove).not.toHaveBeenCalled()
|
||||
expect(atom.confirm).toHaveBeenCalled()
|
||||
|
||||
@ -494,7 +494,7 @@ describe "Editor", ->
|
||||
expect(editor.getCursorView().position()).toEqual { top: 5 * editor.lineHeight, left: 5 * editor.charWidth }
|
||||
|
||||
# ensure we clean up font size subscription
|
||||
editor.trigger('close')
|
||||
editor.trigger('core:close')
|
||||
rootView.setFontSize(22)
|
||||
expect(editor.css('font-size')).toBe '30px'
|
||||
|
||||
@ -1494,18 +1494,18 @@ describe "Editor", ->
|
||||
|
||||
describe "width", ->
|
||||
it "sets the width based on largest line number", ->
|
||||
expect(editor.gutter.lineNumbers.outerWidth()).toBe editor.charWidth * 2
|
||||
expect(editor.gutter.lineNumbers.outerWidth()).toBe(editor.charWidth * 2 + editor.gutter.calculateLineNumberPadding())
|
||||
|
||||
it "updates the width and the left position of the scroll view when total number of lines gains a digit", ->
|
||||
editor.setText("")
|
||||
|
||||
expect(editor.gutter.lineNumbers.outerWidth()).toBe editor.charWidth * 1
|
||||
expect(editor.gutter.lineNumbers.outerWidth()).toBe(editor.charWidth * 1 + editor.gutter.calculateLineNumberPadding())
|
||||
expect(parseInt(editor.scrollView.css('left'))).toBe editor.gutter.outerWidth()
|
||||
|
||||
for i in [1..9] # Ends on an empty line 10
|
||||
editor.insertText "#{i}\n"
|
||||
|
||||
expect(editor.gutter.lineNumbers.outerWidth()).toBe editor.charWidth * 2
|
||||
expect(editor.gutter.lineNumbers.outerWidth()).toBe(editor.charWidth * 2 + editor.gutter.calculateLineNumberPadding())
|
||||
expect(parseInt(editor.scrollView.css('left'))).toBe editor.gutter.outerWidth()
|
||||
|
||||
describe "when lines are inserted", ->
|
||||
@ -1589,18 +1589,113 @@ describe "Editor", ->
|
||||
expect(miniEditor.gutter).toBeHidden()
|
||||
expect(miniEditor.scrollView.css('left')).toBe '0px'
|
||||
|
||||
it "highlights the line where the initial cursor position is", ->
|
||||
{ row, column } = editor.getCursorBufferPosition()
|
||||
expect(row).toBe 0
|
||||
it "doesn't highlight the only line", ->
|
||||
miniEditor = new Editor(mini: true)
|
||||
miniEditor.attachToDom()
|
||||
expect(miniEditor.getCursorBufferPosition().row).toBe 0
|
||||
expect(miniEditor.find('.line.cursor-line').length).toBe 0
|
||||
|
||||
|
||||
describe "gutter line highlighting", ->
|
||||
beforeEach ->
|
||||
editor.attachToDom(heightInLines: 5.5)
|
||||
|
||||
describe "when there is no wrapping", ->
|
||||
it "highlights the line where the initial cursor position is", ->
|
||||
expect(editor.getCursorBufferPosition().row).toBe 0
|
||||
expect(editor.find('.line-number.cursor-line-number').length).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number').text()).toBe "1"
|
||||
|
||||
it "updates the highlighted line when the cursor position changes", ->
|
||||
editor.setCursorBufferPosition([1,0])
|
||||
expect(editor.getCursorBufferPosition().row).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number').length).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number').text()).toBe "2"
|
||||
|
||||
describe "when there is wrapping", ->
|
||||
beforeEach ->
|
||||
editor.attachToDom(30)
|
||||
editor.setSoftWrap(true)
|
||||
setEditorWidthInChars(editor, 20)
|
||||
|
||||
it "highlights the line where the initial cursor position is", ->
|
||||
expect(editor.getCursorBufferPosition().row).toBe 0
|
||||
expect(editor.find('.line-number.cursor-line-number.cursor-line-number-background').length).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number.cursor-line-number-background').text()).toBe "1"
|
||||
|
||||
it "updates the highlighted line when the cursor position changes", ->
|
||||
editor.setCursorBufferPosition([1,0])
|
||||
expect(editor.getCursorBufferPosition().row).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number.cursor-line-number-background').length).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number.cursor-line-number-background').text()).toBe "2"
|
||||
|
||||
describe "when the selection spans multiple lines", ->
|
||||
beforeEach ->
|
||||
editor.attachToDom(30)
|
||||
|
||||
it "doesn't highlight the backround", ->
|
||||
editor.getSelection().setBufferRange(new Range([0,0],[2,0]))
|
||||
expect(editor.getSelection().isSingleScreenLine()).toBe false
|
||||
expect(editor.find('.line-number.cursor-line-number').length).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number.cursor-line-number-background').length).toBe 0
|
||||
expect(editor.find('.line-number.cursor-line-number').text()).toBe "3"
|
||||
|
||||
it "when a newline is deleted with backspace, the line number of the new cursor position is highlighted", ->
|
||||
editor.setCursorScreenPosition([1,0])
|
||||
editor.backspace()
|
||||
expect(editor.find('.line-number.cursor-line-number').length).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number').text()).toBe "1"
|
||||
expect(editor.find('.line-number.cursor-line-number-background').length).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number-background').text()).toBe "1"
|
||||
|
||||
it "updates the highlighted line when the cursor position changes", ->
|
||||
editor.setCursorBufferPosition([1,0])
|
||||
{ row, column } = editor.getCursorBufferPosition()
|
||||
expect(row).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number').length).toBe 1
|
||||
expect(editor.find('.line-number.cursor-line-number').text()).toBe "2"
|
||||
describe "line highlighting", ->
|
||||
beforeEach ->
|
||||
editor.attachToDom(30)
|
||||
|
||||
describe "when there is no wrapping", ->
|
||||
it "highlights the line where the initial cursor position is", ->
|
||||
expect(editor.getCursorBufferPosition().row).toBe 0
|
||||
expect(editor.find('.line.cursor-line').length).toBe 1
|
||||
expect(editor.find('.line.cursor-line').text()).toBe buffer.lineForRow(0)
|
||||
|
||||
it "updates the highlighted line when the cursor position changes", ->
|
||||
editor.setCursorBufferPosition([1,0])
|
||||
expect(editor.getCursorBufferPosition().row).toBe 1
|
||||
expect(editor.find('.line.cursor-line').length).toBe 1
|
||||
expect(editor.find('.line.cursor-line').text()).toBe buffer.lineForRow(1)
|
||||
|
||||
it "when a newline is deleted with backspace, the line of the new cursor position is highlighted", ->
|
||||
editor.setCursorScreenPosition([1,0])
|
||||
editor.backspace()
|
||||
expect(editor.find('.line.cursor-line').length).toBe 1
|
||||
|
||||
describe "when there is wrapping", ->
|
||||
beforeEach ->
|
||||
editor.setSoftWrap(true)
|
||||
setEditorWidthInChars(editor, 20)
|
||||
|
||||
it "highlights the line where the initial cursor position is", ->
|
||||
expect(editor.getCursorBufferPosition().row).toBe 0
|
||||
expect(editor.find('.line.cursor-line').length).toBe 1
|
||||
expect(editor.find('.line.cursor-line').text()).toBe 'var quicksort = '
|
||||
|
||||
it "updates the highlighted line when the cursor position changes", ->
|
||||
editor.setCursorBufferPosition([1,0])
|
||||
expect(editor.getCursorBufferPosition().row).toBe 1
|
||||
expect(editor.find('.line.cursor-line').length).toBe 1
|
||||
expect(editor.find('.line.cursor-line').text()).toBe ' var sort = '
|
||||
|
||||
describe "when there is a selection", ->
|
||||
it "highlights if the selection is contained to one line", ->
|
||||
editor.getSelection().setBufferRange(new Range([0,0],[0,1]))
|
||||
expect(editor.getSelection().isSingleScreenLine()).toBe true
|
||||
expect(editor.find('.line.cursor-line').length).toBe 1
|
||||
expect(editor.find('.line.cursor-line').text()).toBe buffer.lineForRow(0)
|
||||
|
||||
it "doesn't highlight if the selection spans multiple lines", ->
|
||||
editor.getSelection().setBufferRange(new Range([0,0],[2,0]))
|
||||
expect(editor.getSelection().isSingleScreenLine()).toBe false
|
||||
expect(editor.find('.line.cursor-line').length).toBe 0
|
||||
|
||||
describe "folding", ->
|
||||
beforeEach ->
|
||||
@ -1612,7 +1707,7 @@ describe "Editor", ->
|
||||
describe "when a fold-selection event is triggered", ->
|
||||
it "folds the lines covered by the selection into a single line with a fold class", ->
|
||||
editor.getSelection().setBufferRange(new Range([4, 29], [7, 4]))
|
||||
editor.trigger 'fold-selection'
|
||||
editor.trigger 'editor:fold-selection'
|
||||
|
||||
expect(editor.renderedLines.find('.line:eq(4)')).toHaveClass('fold')
|
||||
expect(editor.renderedLines.find('.line:eq(5)').text()).toBe '8'
|
||||
@ -1623,7 +1718,7 @@ describe "Editor", ->
|
||||
describe "when a fold placeholder line is clicked", ->
|
||||
it "removes the associated fold and places the cursor at its beginning", ->
|
||||
editor.setCursorBufferPosition([3,0])
|
||||
editor.trigger 'fold-current-row'
|
||||
editor.trigger 'editor:fold-current-row'
|
||||
|
||||
editor.find('.fold.line').mousedown()
|
||||
|
||||
@ -1636,10 +1731,10 @@ describe "Editor", ->
|
||||
describe "when the unfold-current-row event is triggered when the cursor is on a fold placeholder line", ->
|
||||
it "removes the associated fold and places the cursor at its beginning", ->
|
||||
editor.setCursorBufferPosition([3,0])
|
||||
editor.trigger 'fold-current-row'
|
||||
editor.trigger 'editor:fold-current-row'
|
||||
|
||||
editor.setCursorBufferPosition([3,0])
|
||||
editor.trigger 'unfold-current-row'
|
||||
editor.trigger 'editor:unfold-current-row'
|
||||
|
||||
expect(editor.find('.fold')).not.toExist()
|
||||
expect(editor.renderedLines.find('.line:eq(4)').text()).toMatch /4-+/
|
||||
|
@ -542,13 +542,13 @@ describe "RootView", ->
|
||||
describe "font size adjustment", ->
|
||||
it "increases/decreases font size when increase/decrease-font-size events are triggered", ->
|
||||
fontSizeBefore = rootView.getFontSize()
|
||||
rootView.trigger 'increase-font-size'
|
||||
rootView.trigger 'root-view:increase-font-size'
|
||||
expect(rootView.getFontSize()).toBe fontSizeBefore + 1
|
||||
rootView.trigger 'increase-font-size'
|
||||
rootView.trigger 'root-view:increase-font-size'
|
||||
expect(rootView.getFontSize()).toBe fontSizeBefore + 2
|
||||
rootView.trigger 'decrease-font-size'
|
||||
rootView.trigger 'root-view:decrease-font-size'
|
||||
expect(rootView.getFontSize()).toBe fontSizeBefore + 1
|
||||
rootView.trigger 'decrease-font-size'
|
||||
rootView.trigger 'root-view:decrease-font-size'
|
||||
expect(rootView.getFontSize()).toBe fontSizeBefore
|
||||
|
||||
it "does not allow the font size to be less than 1", ->
|
||||
|
@ -64,28 +64,28 @@ describe "Autocomplete", ->
|
||||
expect(autocomplete.matchesList.find('li:eq(1)')).toHaveText('shift')
|
||||
|
||||
it 'autocompletes word when there is only a suffix', ->
|
||||
editor.getBuffer().insert([10,0] ,"extra:e:extra")
|
||||
editor.getBuffer().insert([10,0] ,"extra:n:extra")
|
||||
editor.setCursorBufferPosition([10,6])
|
||||
autocomplete.attach()
|
||||
|
||||
expect(editor.lineForBufferRow(10)).toBe "extra:while:extra"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [10,10]
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[10,6], [10,10]]
|
||||
expect(editor.lineForBufferRow(10)).toBe "extra:function:extra"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [10,13]
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[10,6], [10,13]]
|
||||
|
||||
expect(autocomplete.matchesList.find('li').length).toBe 1
|
||||
expect(autocomplete.matchesList.find('li:eq(0)')).toHaveText('while')
|
||||
expect(autocomplete.matchesList.find('li').length).toBe 2
|
||||
expect(autocomplete.matchesList.find('li:eq(0)')).toHaveText('function')
|
||||
expect(autocomplete.matchesList.find('li:eq(1)')).toHaveText('return')
|
||||
|
||||
it 'autocompletes word when there is a prefix and suffix', ->
|
||||
it 'autocompletes word when there is a single prefix and suffix match', ->
|
||||
editor.getBuffer().insert([8,43] ,"q")
|
||||
editor.setCursorBufferPosition([8,44])
|
||||
autocomplete.attach()
|
||||
|
||||
expect(editor.lineForBufferRow(8)).toBe " return sort(left).concat(pivot).concat(quicksort(right));"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [8,48]
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[8,44], [8,48]]
|
||||
expect(editor.getCursorBufferPosition()).toEqual [8,52]
|
||||
expect(editor.getSelection().getBufferRange().isEmpty()).toBeTruthy()
|
||||
|
||||
expect(autocomplete.matchesList.find('li').length).toBe 1
|
||||
expect(autocomplete.matchesList.find('li:eq(0)')).toHaveText('quicksort')
|
||||
expect(autocomplete.matchesList.find('li').length).toBe 0
|
||||
|
||||
it "show's that there are no matches found when there is no prefix or suffix", ->
|
||||
editor.setCursorBufferPosition([10, 0])
|
||||
@ -102,10 +102,9 @@ describe "Autocomplete", ->
|
||||
|
||||
expect(editor.lineForBufferRow(10)).toBe "extra:shift:extra"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [10,11]
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[10,7],[10,11]]
|
||||
expect(editor.getSelection().getBufferRange().isEmpty()).toBeTruthy()
|
||||
|
||||
expect(autocomplete.matchesList.find('li').length).toBe 1
|
||||
expect(autocomplete.matchesList.find('li:eq(0)')).toHaveText('shift')
|
||||
expect(autocomplete.matchesList.find('li').length).toBe 0
|
||||
|
||||
it 'autocompletes word when there is only a suffix', ->
|
||||
editor.getBuffer().insert([10,0] ,"extra:current:extra")
|
||||
@ -124,23 +123,34 @@ describe "Autocomplete", ->
|
||||
autocomplete.attach()
|
||||
|
||||
expect(editor.lineForBufferRow(5)).toBe " concat = items.shift();"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [5,11]
|
||||
expect(editor.getSelection().getBufferRange()).toEqual [[5,7], [5,11]]
|
||||
expect(editor.getCursorBufferPosition()).toEqual [5,12]
|
||||
expect(editor.getSelection().getBufferRange().isEmpty()).toBeTruthy()
|
||||
|
||||
expect(autocomplete.matchesList.find('li').length).toBe 1
|
||||
expect(autocomplete.matchesList.find('li:eq(0)')).toHaveText('concat')
|
||||
expect(autocomplete.matchesList.find('li').length).toBe 0
|
||||
|
||||
it 'replaces selection with selected match, moves the cursor to the end of the match, and removes the autocomplete menu', ->
|
||||
editor.getBuffer().insert([10,0] ,"extra:sort:extra")
|
||||
editor.setSelectedBufferRange [[10,7], [10,9]]
|
||||
autocomplete.attach()
|
||||
|
||||
expect(editor.lineForBufferRow(10)).toBe "extra:shift:extra"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [10,11]
|
||||
expect(editor.getSelection().isEmpty()).toBeTruthy()
|
||||
expect(editor.find('.autocomplete')).not.toExist()
|
||||
|
||||
describe 'autocomplete:confirm event', ->
|
||||
it 'replaces selection with selected match, moves the cursor to the end of the match, and removes the autocomplete menu', ->
|
||||
editor.getBuffer().insert([10,0] ,"extra:sort:extra")
|
||||
editor.setSelectedBufferRange [[10,7], [10,9]]
|
||||
autocomplete.attach()
|
||||
miniEditor.trigger "autocomplete:confirm"
|
||||
describe "where there are matches", ->
|
||||
describe "where there is no selection", ->
|
||||
it "closes the menu and moves the cursor to the end", ->
|
||||
editor.getBuffer().insert([10,0] ,"extra:sh:extra")
|
||||
editor.setCursorBufferPosition([10,8])
|
||||
autocomplete.attach()
|
||||
miniEditor.trigger "autocomplete:confirm"
|
||||
|
||||
expect(editor.lineForBufferRow(10)).toBe "extra:shift:extra"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [10,11]
|
||||
expect(editor.getSelection().isEmpty()).toBeTruthy()
|
||||
expect(editor.find('.autocomplete')).not.toExist()
|
||||
expect(editor.lineForBufferRow(10)).toBe "extra:shift:extra"
|
||||
expect(editor.getCursorBufferPosition()).toEqual [10,11]
|
||||
expect(editor.getSelection().isEmpty()).toBeTruthy()
|
||||
expect(editor.find('.autocomplete')).not.toExist()
|
||||
|
||||
describe "when there are no matches", ->
|
||||
it "closes the menu without changing the buffer", ->
|
||||
@ -190,13 +200,13 @@ describe "Autocomplete", ->
|
||||
editor.setCursorBufferPosition([10,6])
|
||||
autocomplete.attach()
|
||||
|
||||
miniEditor.trigger "move-up"
|
||||
miniEditor.trigger "core:move-up"
|
||||
expect(editor.lineForBufferRow(10)).toBe "extra:concat:extra"
|
||||
expect(autocomplete.find('li:eq(0)')).not.toHaveClass('selected')
|
||||
expect(autocomplete.find('li:eq(1)')).not.toHaveClass('selected')
|
||||
expect(autocomplete.find('li:eq(7)')).toHaveClass('selected')
|
||||
|
||||
miniEditor.trigger "move-up"
|
||||
miniEditor.trigger "core:move-up"
|
||||
expect(editor.lineForBufferRow(10)).toBe "extra:right:extra"
|
||||
expect(autocomplete.find('li:eq(0)')).not.toHaveClass('selected')
|
||||
expect(autocomplete.find('li:eq(7)')).not.toHaveClass('selected')
|
||||
@ -213,10 +223,10 @@ describe "Autocomplete", ->
|
||||
expect(matchesList.height()).toBeLessThan matchesList[0].scrollHeight
|
||||
|
||||
matchCount = matchesList.find('li').length
|
||||
miniEditor.trigger 'move-up'
|
||||
miniEditor.trigger 'core:move-up'
|
||||
expect(matchesList.scrollBottom()).toBe matchesList[0].scrollHeight
|
||||
|
||||
miniEditor.trigger 'move-up' for i in [1...matchCount]
|
||||
miniEditor.trigger 'core:move-up' for i in [1...matchCount]
|
||||
expect(matchesList.scrollTop()).toBe 0
|
||||
|
||||
describe 'move-down event', ->
|
||||
@ -225,12 +235,12 @@ describe "Autocomplete", ->
|
||||
editor.setCursorBufferPosition([10,7])
|
||||
autocomplete.attach()
|
||||
|
||||
miniEditor.trigger "move-down"
|
||||
miniEditor.trigger "core:move-down"
|
||||
expect(editor.lineForBufferRow(10)).toBe "extra:shift:extra"
|
||||
expect(autocomplete.find('li:eq(0)')).not.toHaveClass('selected')
|
||||
expect(autocomplete.find('li:eq(1)')).toHaveClass('selected')
|
||||
|
||||
miniEditor.trigger "move-down"
|
||||
miniEditor.trigger "core:move-down"
|
||||
expect(editor.lineForBufferRow(10)).toBe "extra:sort:extra"
|
||||
expect(autocomplete.find('li:eq(0)')).toHaveClass('selected')
|
||||
expect(autocomplete.find('li:eq(1)')).not.toHaveClass('selected')
|
||||
@ -246,10 +256,10 @@ describe "Autocomplete", ->
|
||||
expect(matchesList.height()).toBeLessThan matchesList[0].scrollHeight
|
||||
|
||||
matchCount = matchesList.find('li').length
|
||||
miniEditor.trigger 'move-down' for i in [1...matchCount]
|
||||
miniEditor.trigger 'core:move-down' for i in [1...matchCount]
|
||||
expect(matchesList.scrollBottom()).toBe matchesList[0].scrollHeight
|
||||
|
||||
miniEditor.trigger 'move-down'
|
||||
miniEditor.trigger 'core:move-down'
|
||||
expect(matchesList.scrollTop()).toBe 0
|
||||
|
||||
describe "when a match is clicked in the match list", ->
|
||||
@ -421,10 +431,10 @@ describe "Autocomplete", ->
|
||||
autocomplete.detach()
|
||||
expect(miniEditor.getText()).toBe ''
|
||||
|
||||
editor.trigger 'move-down'
|
||||
editor.trigger 'core:move-down'
|
||||
expect(editor.getCursorBufferPosition().row).toBe 1
|
||||
|
||||
editor.trigger 'move-up'
|
||||
editor.trigger 'core:move-up'
|
||||
expect(editor.getCursorBufferPosition().row).toBe 0
|
||||
|
||||
|
||||
|
@ -320,15 +320,15 @@ describe "CommandPanel", ->
|
||||
|
||||
rootView.trigger 'command-panel:toggle'
|
||||
|
||||
commandPanel.miniEditor.trigger 'move-up'
|
||||
commandPanel.miniEditor.trigger 'core:move-up'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 's/twinkies/wheatgrass/g'
|
||||
commandPanel.miniEditor.trigger 'move-up'
|
||||
commandPanel.miniEditor.trigger 'core:move-up'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 's/war/peace/g'
|
||||
commandPanel.miniEditor.trigger 'move-up'
|
||||
commandPanel.miniEditor.trigger 'core:move-up'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 's/war/peace/g'
|
||||
commandPanel.miniEditor.trigger 'move-down'
|
||||
commandPanel.miniEditor.trigger 'core:move-down'
|
||||
expect(commandPanel.miniEditor.getText()).toBe 's/twinkies/wheatgrass/g'
|
||||
commandPanel.miniEditor.trigger 'move-down'
|
||||
commandPanel.miniEditor.trigger 'core:move-down'
|
||||
expect(commandPanel.miniEditor.getText()).toBe ''
|
||||
|
||||
describe "when the preview list is focused with search operations", ->
|
||||
@ -345,30 +345,30 @@ describe "CommandPanel", ->
|
||||
expect(previewList.find('li:eq(0)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[0]
|
||||
|
||||
previewList.trigger 'move-up'
|
||||
previewList.trigger 'core:move-up'
|
||||
expect(previewList.find('li:eq(0)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[0]
|
||||
|
||||
previewList.trigger 'move-down'
|
||||
previewList.trigger 'core:move-down'
|
||||
expect(previewList.find('li:eq(1)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[1]
|
||||
|
||||
previewList.trigger 'move-down'
|
||||
previewList.trigger 'core:move-down'
|
||||
expect(previewList.find('li:eq(2)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[2]
|
||||
|
||||
previewList.trigger 'move-up'
|
||||
previewList.trigger 'core:move-up'
|
||||
expect(previewList.find('li:eq(1)')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe previewList.getOperations()[1]
|
||||
|
||||
_.times previewList.getOperations().length, -> previewList.trigger 'move-down'
|
||||
_.times previewList.getOperations().length, -> previewList.trigger 'core:move-down'
|
||||
|
||||
expect(previewList.find('li:last')).toHaveClass 'selected'
|
||||
expect(previewList.getSelectedOperation()).toBe _.last(previewList.getOperations())
|
||||
|
||||
expect(previewList.scrollBottom()).toBeCloseTo previewList.prop('scrollHeight'), -1
|
||||
|
||||
_.times previewList.getOperations().length, -> previewList.trigger 'move-up'
|
||||
_.times previewList.getOperations().length, -> previewList.trigger 'core:move-up'
|
||||
|
||||
describe "when command-panel:execute is triggered on the preview list", ->
|
||||
it "opens the operation's buffer, selects the search result, and focuses the active editor", ->
|
||||
@ -376,7 +376,7 @@ describe "CommandPanel", ->
|
||||
executeHandler = jasmine.createSpy('executeHandler')
|
||||
commandPanel.on 'command-panel:execute', executeHandler
|
||||
|
||||
_.times 4, -> previewList.trigger 'move-down'
|
||||
_.times 4, -> previewList.trigger 'core:move-down'
|
||||
operation = previewList.getSelectedOperation()
|
||||
|
||||
previewList.trigger 'command-panel:execute'
|
||||
|
@ -21,7 +21,7 @@ describe 'FuzzyFinder', ->
|
||||
it "shows the FuzzyFinder or hides it and returns focus to the active editor if it already showing", ->
|
||||
rootView.attachToDom()
|
||||
expect(rootView.find('.fuzzy-finder')).not.toExist()
|
||||
rootView.find('.editor').trigger 'split-right'
|
||||
rootView.find('.editor').trigger 'editor:split-right'
|
||||
[editor1, editor2] = rootView.find('.editor').map -> $(this).view()
|
||||
|
||||
rootView.trigger 'fuzzy-finder:toggle-file-finder'
|
||||
@ -67,7 +67,7 @@ describe 'FuzzyFinder', ->
|
||||
|
||||
describe "when a path is highlighted", ->
|
||||
it "opens the file associated with that path in the editor", ->
|
||||
finder.trigger 'move-down'
|
||||
finder.trigger 'core:move-down'
|
||||
selectedLi = finder.find('li:eq(1)')
|
||||
|
||||
expectedPath = rootView.project.resolve(selectedLi.text())
|
||||
@ -96,7 +96,7 @@ describe 'FuzzyFinder', ->
|
||||
it "shows the FuzzyFinder or hides it and returns focus to the active editor if it already showing", ->
|
||||
rootView.attachToDom()
|
||||
expect(rootView.find('.fuzzy-finder')).not.toExist()
|
||||
rootView.find('.editor').trigger 'split-right'
|
||||
rootView.find('.editor').trigger 'editor:split-right'
|
||||
[editor1, editor2] = rootView.find('.editor').map -> $(this).view()
|
||||
|
||||
rootView.trigger 'fuzzy-finder:toggle-buffer-finder'
|
||||
@ -211,28 +211,27 @@ describe 'FuzzyFinder', ->
|
||||
expect(finder.find('li:eq(0)')).toHaveClass "selected"
|
||||
expect(finder.find('li:eq(2)')).not.toHaveClass "selected"
|
||||
|
||||
finder.miniEditor.trigger keydownEvent('down')
|
||||
finder.miniEditor.trigger keydownEvent('down')
|
||||
finder.miniEditor.trigger 'core:move-down'
|
||||
finder.miniEditor.trigger 'core:move-down'
|
||||
|
||||
expect(finder.find('li:eq(0)')).not.toHaveClass "selected"
|
||||
expect(finder.find('li:eq(2)')).toHaveClass "selected"
|
||||
|
||||
finder.miniEditor.trigger keydownEvent('up')
|
||||
finder.miniEditor.trigger 'core:move-up'
|
||||
|
||||
expect(finder.find('li:eq(0)')).not.toHaveClass "selected"
|
||||
expect(finder.find('li:eq(1)')).toHaveClass "selected"
|
||||
expect(finder.find('li:eq(2)')).not.toHaveClass "selected"
|
||||
|
||||
it "does not fall off the end or begining of the list", ->
|
||||
expect(finder.find('li:first')).toHaveClass "selected"
|
||||
finder.miniEditor.trigger keydownEvent('up')
|
||||
it "wraps around when at the end or begining of the list", ->
|
||||
expect(finder.find('li:first')).toHaveClass "selected"
|
||||
|
||||
for i in [1..finder.pathList.children().length+2]
|
||||
finder.miniEditor.trigger keydownEvent('down')
|
||||
|
||||
finder.miniEditor.trigger 'core:move-up'
|
||||
expect(finder.find('li:last')).toHaveClass "selected"
|
||||
|
||||
finder.miniEditor.trigger 'core:move-down'
|
||||
expect(finder.find('li:first')).toHaveClass "selected"
|
||||
|
||||
describe "when the fuzzy finder loses focus", ->
|
||||
it "detaches itself", ->
|
||||
rootView.attachToDom()
|
||||
|
@ -10,14 +10,14 @@ describe "TreeView", ->
|
||||
[rootView, project, treeView, sampleJs, sampleTxt] = []
|
||||
|
||||
beforeEach ->
|
||||
rootView = new RootView(require.resolve('fixtures/'))
|
||||
rootView = new RootView(require.resolve('fixtures/tree-view'))
|
||||
project = rootView.project
|
||||
|
||||
rootView.activateExtension(TreeView)
|
||||
treeView = rootView.find(".tree-view").view()
|
||||
treeView.root = treeView.find('> li:first').view()
|
||||
sampleJs = treeView.find('.file:contains(sample.js)')
|
||||
sampleTxt = treeView.find('.file:contains(sample.txt)')
|
||||
sampleJs = treeView.find('.file:contains(tree-view.js)')
|
||||
sampleTxt = treeView.find('.file:contains(tree-view.txt)')
|
||||
|
||||
expect(treeView.root.directory.subscriptionCount()).toBeGreaterThan 0
|
||||
|
||||
@ -27,21 +27,21 @@ describe "TreeView", ->
|
||||
describe ".initialize(project)", ->
|
||||
it "renders the root of the project and its contents alphabetically with subdirectories first in a collapsed state", ->
|
||||
expect(treeView.root.find('> .header .disclosure-arrow')).toHaveText('▾')
|
||||
expect(treeView.root.find('> .header .name')).toHaveText('fixtures/')
|
||||
expect(treeView.root.find('> .header .name')).toHaveText('tree-view/')
|
||||
|
||||
rootEntries = treeView.root.find('.entries')
|
||||
subdir0 = rootEntries.find('> li:eq(0)')
|
||||
expect(subdir0.find('.disclosure-arrow')).toHaveText('▸')
|
||||
expect(subdir0.find('.name')).toHaveText('dir/')
|
||||
expect(subdir0.find('.name')).toHaveText('dir1/')
|
||||
expect(subdir0.find('.entries')).not.toExist()
|
||||
|
||||
subdir2 = rootEntries.find('> li:eq(3)')
|
||||
subdir2 = rootEntries.find('> li:eq(1)')
|
||||
expect(subdir2.find('.disclosure-arrow')).toHaveText('▸')
|
||||
expect(subdir2.find('.name')).toHaveText('zed/')
|
||||
expect(subdir2.find('.name')).toHaveText('dir2/')
|
||||
expect(subdir2.find('.entries')).not.toExist()
|
||||
|
||||
expect(rootEntries.find('> .file:contains(sample.js)')).toExist()
|
||||
expect(rootEntries.find('> .file:contains(sample.txt)')).toExist()
|
||||
expect(rootEntries.find('> .file:contains(tree-view.js)')).toExist()
|
||||
expect(rootEntries.find('> .file:contains(tree-view.txt)')).toExist()
|
||||
|
||||
it "selects the rootview", ->
|
||||
expect(treeView.selectedEntry()).toEqual treeView.root
|
||||
@ -84,7 +84,7 @@ describe "TreeView", ->
|
||||
newRootView?.deactivate()
|
||||
|
||||
it "restores expanded directories and selected file when deserialized", ->
|
||||
treeView.find('.directory:contains(zed)').click()
|
||||
treeView.find('.directory:contains(dir1)').click()
|
||||
sampleJs.click()
|
||||
newRootView = RootView.deserialize(rootView.serialize())
|
||||
rootView.deactivate() # Deactivates previous TreeView
|
||||
@ -94,8 +94,8 @@ describe "TreeView", ->
|
||||
newTreeView = newRootView.find(".tree-view").view()
|
||||
|
||||
expect(newTreeView).toExist()
|
||||
expect(newTreeView.selectedEntry()).toMatchSelector(".file:contains(sample.js)")
|
||||
expect(newTreeView.find(".directory:contains(zed)")).toHaveClass("expanded")
|
||||
expect(newTreeView.selectedEntry()).toMatchSelector(".file:contains(tree-view.js)")
|
||||
expect(newTreeView.find(".directory:contains(dir1)")).toHaveClass("expanded")
|
||||
|
||||
it "restores the focus state of the tree view", ->
|
||||
rootView.attachToDom()
|
||||
@ -112,7 +112,7 @@ describe "TreeView", ->
|
||||
expect(newTreeView).toMatchSelector ':focus'
|
||||
|
||||
it "restores the scroll top when toggled", ->
|
||||
rootView.height(100)
|
||||
rootView.height(5)
|
||||
rootView.attachToDom()
|
||||
expect(treeView).toBeVisible()
|
||||
treeView.focus()
|
||||
@ -162,11 +162,11 @@ describe "TreeView", ->
|
||||
|
||||
describe "if the current file has a path", ->
|
||||
it "shows and focuses the tree view and selects the file", ->
|
||||
rootView.open('dir/a')
|
||||
rootView.open('dir1/file1')
|
||||
rootView.trigger 'tree-view:reveal-active-file'
|
||||
expect(treeView.hasParent()).toBeTruthy()
|
||||
expect(treeView.focus).toHaveBeenCalled()
|
||||
expect(treeView.selectedEntry().getPath()).toMatch /dir\/a$/
|
||||
expect(treeView.selectedEntry().getPath()).toMatch /dir1\/file1$/
|
||||
|
||||
describe "if the current file has no path", ->
|
||||
it "shows and focuses the tree view, but does not attempt to select a specific file", ->
|
||||
@ -196,7 +196,7 @@ describe "TreeView", ->
|
||||
|
||||
describe "when a directory's disclosure arrow is clicked", ->
|
||||
it "expands / collapses the associated directory", ->
|
||||
subdir = treeView.root.find('.entries > li:contains(dir/)').view()
|
||||
subdir = treeView.root.find('.entries > li:contains(dir1/)').view()
|
||||
|
||||
expect(subdir.disclosureArrow).toHaveText('▸')
|
||||
expect(subdir.find('.entries')).not.toExist()
|
||||
@ -211,10 +211,10 @@ describe "TreeView", ->
|
||||
expect(subdir.find('.entries')).not.toExist()
|
||||
|
||||
it "restores the expansion state of descendant directories", ->
|
||||
child = treeView.root.find('.entries > li:contains(dir/)').view()
|
||||
child = treeView.root.find('.entries > li:contains(dir1/)').view()
|
||||
child.disclosureArrow.click()
|
||||
|
||||
grandchild = child.find('.entries > li:contains(a-dir/)').view()
|
||||
grandchild = child.find('.entries > li:contains(sub-dir1/)').view()
|
||||
grandchild.disclosureArrow.click()
|
||||
|
||||
treeView.root.disclosureArrow.click()
|
||||
@ -222,16 +222,16 @@ describe "TreeView", ->
|
||||
treeView.root.disclosureArrow.click()
|
||||
|
||||
# previously expanded descendants remain expanded
|
||||
expect(treeView.root.find('> .entries > li:contains(dir/) > .entries > li:contains(a-dir/) > .entries').length).toBe 1
|
||||
expect(treeView.root.find('> .entries > li:contains(dir1/) > .entries > li:contains(sub-dir1/) > .entries').length).toBe 1
|
||||
|
||||
# collapsed descendants remain collapsed
|
||||
expect(treeView.root.find('> .entries > li.contains(zed/) > .entries')).not.toExist()
|
||||
expect(treeView.root.find('> .entries > li.contains(dir2/) > .entries')).not.toExist()
|
||||
|
||||
it "when collapsing a directory, removes change subscriptions from the collapsed directory and its descendants", ->
|
||||
child = treeView.root.entries.find('li:contains(dir/)').view()
|
||||
child = treeView.root.entries.find('li:contains(dir1/)').view()
|
||||
child.disclosureArrow.click()
|
||||
|
||||
grandchild = child.entries.find('li:contains(a-dir/)').view()
|
||||
grandchild = child.entries.find('li:contains(sub-dir1/)').view()
|
||||
grandchild.disclosureArrow.click()
|
||||
|
||||
expect(treeView.root.directory.subscriptionCount()).toBe 1
|
||||
@ -250,20 +250,20 @@ describe "TreeView", ->
|
||||
|
||||
sampleJs.trigger clickEvent(originalEvent: { detail: 1 })
|
||||
expect(sampleJs).toHaveClass 'selected'
|
||||
expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/sample.js')
|
||||
expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.js')
|
||||
expect(rootView.getActiveEditor().isFocused).toBeFalsy()
|
||||
|
||||
sampleTxt.trigger clickEvent(originalEvent: { detail: 1 })
|
||||
expect(sampleTxt).toHaveClass 'selected'
|
||||
expect(treeView.find('.selected').length).toBe 1
|
||||
expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/sample.txt')
|
||||
expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.txt')
|
||||
expect(rootView.getActiveEditor().isFocused).toBeFalsy()
|
||||
|
||||
describe "when a file is double-clicked", ->
|
||||
it "selects the file and opens it in the active editor on the first click, then changes focus to the active editor on the second", ->
|
||||
sampleJs.trigger clickEvent(originalEvent: { detail: 1 })
|
||||
expect(sampleJs).toHaveClass 'selected'
|
||||
expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/sample.js')
|
||||
expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.js')
|
||||
expect(rootView.getActiveEditor().isFocused).toBeFalsy()
|
||||
|
||||
sampleJs.trigger clickEvent(originalEvent: { detail: 2 })
|
||||
@ -288,15 +288,15 @@ describe "TreeView", ->
|
||||
describe "when a new file is opened in the active editor", ->
|
||||
it "is selected in the tree view if the file's entry visible", ->
|
||||
sampleJs.click()
|
||||
rootView.open(require.resolve('fixtures/sample.txt'))
|
||||
rootView.open(require.resolve('fixtures/tree-view/tree-view.txt'))
|
||||
|
||||
expect(sampleTxt).toHaveClass 'selected'
|
||||
expect(treeView.find('.selected').length).toBe 1
|
||||
|
||||
it "selected a file's parent dir if the file's entry is not visible", ->
|
||||
rootView.open(require.resolve('fixtures/dir/a-dir/oh-git'))
|
||||
rootView.open(require.resolve('fixtures/tree-view/dir1/sub-dir1/sub-file1'))
|
||||
|
||||
dirView = treeView.root.find('.directory:contains(dir)').view()
|
||||
dirView = treeView.root.find('.directory:contains(dir1)').view()
|
||||
expect(dirView).toHaveClass 'selected'
|
||||
|
||||
describe "when a different editor becomes active", ->
|
||||
@ -314,11 +314,11 @@ describe "TreeView", ->
|
||||
afterEach ->
|
||||
expect(treeView.find('.selected').length).toBeLessThan 2
|
||||
|
||||
describe "move-down", ->
|
||||
describe "core:move-down", ->
|
||||
describe "when a collapsed directory is selected", ->
|
||||
it "skips to the next directory", ->
|
||||
treeView.root.find('.directory:eq(0)').click()
|
||||
treeView.trigger 'move-down'
|
||||
treeView.trigger 'core:move-down'
|
||||
expect(treeView.root.find('.directory:eq(1)')).toHaveClass 'selected'
|
||||
|
||||
describe "when an expanded directory is selected", ->
|
||||
@ -327,7 +327,7 @@ describe "TreeView", ->
|
||||
subdir.expand()
|
||||
subdir.click()
|
||||
|
||||
treeView.trigger 'move-down'
|
||||
treeView.trigger 'core:move-down'
|
||||
|
||||
expect(subdir.entries.find('.entry:first')).toHaveClass 'selected'
|
||||
|
||||
@ -337,7 +337,7 @@ describe "TreeView", ->
|
||||
subdir1.expand()
|
||||
subdir1.entries.find('.entry:last').click()
|
||||
|
||||
treeView.trigger 'move-down'
|
||||
treeView.trigger 'core:move-down'
|
||||
|
||||
expect(treeView.root.find('.entries > .entry:eq(2)')).toHaveClass 'selected'
|
||||
|
||||
@ -346,21 +346,21 @@ describe "TreeView", ->
|
||||
|
||||
beforeEach ->
|
||||
nested = treeView.root.find('.directory:eq(2)').view()
|
||||
expect(nested.find('.header').text()).toContain 'nested'
|
||||
expect(nested.find('.header').text()).toContain 'nested/'
|
||||
nested.expand()
|
||||
nested2 = nested.entries.find('.entry:last').view()
|
||||
nested2.click()
|
||||
|
||||
describe "when the directory is collapsed", ->
|
||||
it "selects the entry after its grandparent directory", ->
|
||||
treeView.trigger 'move-down'
|
||||
treeView.trigger 'core:move-down'
|
||||
expect(nested.next()).toHaveClass 'selected'
|
||||
|
||||
describe "when the directory is expanded", ->
|
||||
it "selects the entry after its grandparent directory", ->
|
||||
nested2.expand()
|
||||
nested2.find('.file').remove() # kill the .gitkeep file, which has to be there but screws the test
|
||||
treeView.trigger 'move-down'
|
||||
treeView.trigger 'core:move-down'
|
||||
expect(nested.next()).toHaveClass 'selected'
|
||||
|
||||
describe "when the last entry of the last directory is selected", ->
|
||||
@ -368,11 +368,11 @@ describe "TreeView", ->
|
||||
lastEntry = treeView.root.find('> .entries .entry:last')
|
||||
lastEntry.click()
|
||||
|
||||
treeView.trigger 'move-down'
|
||||
treeView.trigger 'core:move-down'
|
||||
|
||||
expect(lastEntry).toHaveClass 'selected'
|
||||
|
||||
describe "move-up", ->
|
||||
describe "core:move-up", ->
|
||||
describe "when there is an expanded directory before the currently selected entry", ->
|
||||
it "selects the last entry in the expanded directory", ->
|
||||
lastDir = treeView.root.find('.directory:last').view()
|
||||
@ -380,7 +380,7 @@ describe "TreeView", ->
|
||||
lastDir.expand()
|
||||
fileAfterDir.click()
|
||||
|
||||
treeView.trigger 'move-up'
|
||||
treeView.trigger 'core:move-up'
|
||||
expect(lastDir.find('.entry:last')).toHaveClass 'selected'
|
||||
|
||||
describe "when there is an entry before the currently selected entry", ->
|
||||
@ -388,7 +388,7 @@ describe "TreeView", ->
|
||||
lastEntry = treeView.root.find('.entry:last')
|
||||
lastEntry.click()
|
||||
|
||||
treeView.trigger 'move-up'
|
||||
treeView.trigger 'core:move-up'
|
||||
|
||||
expect(lastEntry.prev()).toHaveClass 'selected'
|
||||
|
||||
@ -398,16 +398,69 @@ describe "TreeView", ->
|
||||
subdir.expand()
|
||||
subdir.find('> .entries > .entry:first').click()
|
||||
|
||||
treeView.trigger 'move-up'
|
||||
treeView.trigger 'core:move-up'
|
||||
|
||||
expect(subdir).toHaveClass 'selected'
|
||||
|
||||
describe "when there is no parent directory or previous entry", ->
|
||||
it "does not change the selection", ->
|
||||
treeView.root.click()
|
||||
treeView.trigger 'move-up'
|
||||
treeView.trigger 'core:move-up'
|
||||
expect(treeView.root).toHaveClass 'selected'
|
||||
|
||||
describe "core:move-to-top", ->
|
||||
it "scrolls to the top", ->
|
||||
treeView.height(100)
|
||||
treeView.attachToDom()
|
||||
$(element).view().expand() for element in treeView.find('.directory')
|
||||
expect(treeView.prop('scrollHeight')).toBeGreaterThan treeView.outerHeight()
|
||||
|
||||
expect(treeView.scrollTop()).toBe 0
|
||||
|
||||
entryCount = treeView.find(".entry").length
|
||||
_.times entryCount, -> treeView.moveDown()
|
||||
expect(treeView.scrollTop()).toBeGreaterThan 0
|
||||
|
||||
treeView.trigger 'core:move-to-top'
|
||||
expect(treeView.scrollTop()).toBe 0
|
||||
|
||||
describe "core:move-to-bottom", ->
|
||||
it "scrolls to the bottom", ->
|
||||
treeView.height(100)
|
||||
treeView.attachToDom()
|
||||
$(element).view().expand() for element in treeView.find('.directory')
|
||||
expect(treeView.prop('scrollHeight')).toBeGreaterThan treeView.outerHeight()
|
||||
|
||||
expect(treeView.scrollTop()).toBe 0
|
||||
treeView.trigger 'core:move-to-bottom'
|
||||
expect(treeView.scrollBottom()).toBe treeView.prop('scrollHeight')
|
||||
|
||||
describe "core:page-up", ->
|
||||
it "scrolls up a page", ->
|
||||
treeView.height(5)
|
||||
treeView.attachToDom()
|
||||
$(element).view().expand() for element in treeView.find('.directory')
|
||||
expect(treeView.prop('scrollHeight')).toBeGreaterThan treeView.outerHeight()
|
||||
|
||||
expect(treeView.scrollTop()).toBe 0
|
||||
treeView.scrollToBottom()
|
||||
scrollTop = treeView.scrollTop()
|
||||
expect(scrollTop).toBeGreaterThan 0
|
||||
|
||||
treeView.trigger 'core:page-up'
|
||||
expect(treeView.scrollTop()).toBe scrollTop - treeView.height()
|
||||
|
||||
describe "core:page-down", ->
|
||||
it "scrolls down a page", ->
|
||||
treeView.height(5)
|
||||
treeView.attachToDom()
|
||||
$(element).view().expand() for element in treeView.find('.directory')
|
||||
expect(treeView.prop('scrollHeight')).toBeGreaterThan treeView.outerHeight()
|
||||
|
||||
expect(treeView.scrollTop()).toBe 0
|
||||
treeView.trigger 'core:page-down'
|
||||
expect(treeView.scrollTop()).toBe treeView.height()
|
||||
|
||||
describe "movement outside of viewable region", ->
|
||||
it "scrolls the tree view to the selected item", ->
|
||||
treeView.height(100)
|
||||
@ -485,9 +538,9 @@ describe "TreeView", ->
|
||||
describe "tree-view:open-selected-entry", ->
|
||||
describe "when a file is selected", ->
|
||||
it "opens the file in the editor and focuses it", ->
|
||||
treeView.root.find('.file:contains(sample.js)').click()
|
||||
treeView.root.find('.file:contains(tree-view.js)').click()
|
||||
treeView.root.trigger 'tree-view:open-selected-entry'
|
||||
expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/sample.js')
|
||||
expect(rootView.getActiveEditor().getPath()).toBe require.resolve('fixtures/tree-view/tree-view.js')
|
||||
expect(rootView.getActiveEditor().isFocused).toBeTruthy()
|
||||
|
||||
describe "when a directory is selected", ->
|
||||
@ -590,6 +643,7 @@ describe "TreeView", ->
|
||||
describe "when the path with a trailing '/' is changed and confirmed", ->
|
||||
describe "when no file or directory exists at the given path", ->
|
||||
it "adds a directory and closes the dialog", ->
|
||||
treeView.attachToDom()
|
||||
newPath = fs.join(dirPath, "new/dir")
|
||||
addDialog.miniEditor.insertText("new/dir/")
|
||||
addDialog.trigger 'tree-view:confirm'
|
||||
@ -597,6 +651,22 @@ describe "TreeView", ->
|
||||
expect(fs.isDirectory(newPath)).toBeTruthy()
|
||||
expect(addDialog.parent()).not.toExist()
|
||||
expect(rootView.getActiveEditor().getPath()).not.toBe newPath
|
||||
expect(treeView).toMatchSelector(':focus')
|
||||
expect(rootView.getActiveEditor().isFocused).toBeFalsy()
|
||||
expect(dirView.find('.directory.selected:contains(new/)').length).toBe(1)
|
||||
|
||||
it "selects the created directory", ->
|
||||
treeView.attachToDom()
|
||||
newPath = fs.join(dirPath, "new2/")
|
||||
addDialog.miniEditor.insertText("new2/")
|
||||
addDialog.trigger 'tree-view:confirm'
|
||||
expect(fs.exists(newPath)).toBeTruthy()
|
||||
expect(fs.isDirectory(newPath)).toBeTruthy()
|
||||
expect(addDialog.parent()).not.toExist()
|
||||
expect(rootView.getActiveEditor().getPath()).not.toBe newPath
|
||||
expect(treeView).toMatchSelector(':focus')
|
||||
expect(rootView.getActiveEditor().isFocused).toBeFalsy()
|
||||
expect(dirView.find('.directory.selected:contains(new2/)').length).toBe(1)
|
||||
|
||||
describe "when a file or directory already exists at the given path", ->
|
||||
it "shows an error message and does not close the dialog", ->
|
||||
@ -736,7 +806,7 @@ describe "TreeView", ->
|
||||
temporaryFilePath = null
|
||||
|
||||
beforeEach ->
|
||||
temporaryFilePath = fs.join(require.resolve('fixtures'), 'temporary')
|
||||
temporaryFilePath = fs.join(require.resolve('fixtures/tree-view'), 'temporary')
|
||||
if fs.exists(temporaryFilePath)
|
||||
fs.remove(temporaryFilePath)
|
||||
waits(20)
|
||||
|
@ -32,7 +32,7 @@ describe "WrapGuide", ->
|
||||
it "updates the wrap guide position", ->
|
||||
initial = wrapGuide.position().left
|
||||
expect(initial).toBeGreaterThan(0)
|
||||
rootView.trigger('increase-font-size')
|
||||
rootView.trigger('root-view:increase-font-size')
|
||||
expect(wrapGuide.position().left).toBeGreaterThan(initial)
|
||||
|
||||
describe "overriding getGuideColumn", ->
|
||||
|
0
spec/fixtures/tree-view/dir1/sub-dir1/sub-file1
vendored
Normal file
0
spec/fixtures/tree-view/dir1/sub-dir1/sub-file1
vendored
Normal file
0
spec/fixtures/tree-view/dir2/file2
vendored
Normal file
0
spec/fixtures/tree-view/dir2/file2
vendored
Normal file
0
spec/fixtures/tree-view/nested/nested2/.gitkeep
vendored
Normal file
0
spec/fixtures/tree-view/nested/nested2/.gitkeep
vendored
Normal file
13
spec/fixtures/tree-view/tree-view.js
vendored
Normal file
13
spec/fixtures/tree-view/tree-view.js
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
var quicksort = function () {
|
||||
var sort = function(items) {
|
||||
if (items.length <= 1) return items;
|
||||
var pivot = items.shift(), current, left = [], right = [];
|
||||
while(items.length > 0) {
|
||||
current = items.shift();
|
||||
current < pivot ? left.push(current) : right.push(current);
|
||||
}
|
||||
return sort(left).concat(pivot).concat(sort(right));
|
||||
};
|
||||
|
||||
return sort(Array.apply(this, arguments));
|
||||
};
|
1
spec/fixtures/tree-view/tree-view.txt
vendored
Normal file
1
spec/fixtures/tree-view/tree-view.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
Some text.
|
@ -35,7 +35,7 @@ describe "fs", ->
|
||||
expect(fs.exists(null)).toBe false
|
||||
|
||||
describe ".join(paths...)", ->
|
||||
it "concatenates the given paths with the directory seperator", ->
|
||||
it "concatenates the given paths with the directory separator", ->
|
||||
expect(fs.join('a')).toBe 'a'
|
||||
expect(fs.join('a', 'b', 'c')).toBe 'a/b/c'
|
||||
expect(fs.join('/a/b/', 'c', 'd')).toBe '/a/b/c/d'
|
||||
@ -83,7 +83,7 @@ describe "fs", ->
|
||||
|
||||
expect(paths.length).toBeGreaterThan 0
|
||||
for path in paths
|
||||
expect(path).not.toMatch /dir/
|
||||
expect(path).not.toMatch /\/dir\//
|
||||
|
||||
describe ".lastModified(path)", ->
|
||||
it "returns a Date object representing the time the file was last modified", ->
|
||||
|
@ -13,10 +13,10 @@ class CursorView extends View
|
||||
hidden: false
|
||||
|
||||
initialize: (@cursor, @editor) ->
|
||||
@cursor.on 'change-screen-position.cursor-view', (position, { bufferChange }) =>
|
||||
@cursor.on 'change-screen-position.cursor-view', (screenPosition, { bufferChange }) =>
|
||||
@updateAppearance()
|
||||
@removeIdleClassTemporarily() unless bufferChange
|
||||
@trigger 'cursor-move', bufferChange: bufferChange
|
||||
@trigger 'cursor-move', {bufferChange}
|
||||
|
||||
@cursor.on 'destroy.cursor-view', => @remove()
|
||||
|
||||
|
@ -91,68 +91,68 @@ class Editor extends View
|
||||
|
||||
bindKeys: ->
|
||||
editorBindings =
|
||||
'move-right': @moveCursorRight
|
||||
'move-left': @moveCursorLeft
|
||||
'move-down': @moveCursorDown
|
||||
'move-up': @moveCursorUp
|
||||
'move-to-next-word': @moveCursorToNextWord
|
||||
'move-to-previous-word': @moveCursorToPreviousWord
|
||||
'select-right': @selectRight
|
||||
'select-left': @selectLeft
|
||||
'select-up': @selectUp
|
||||
'select-down': @selectDown
|
||||
'select-word': @selectWord
|
||||
'newline': @insertNewline
|
||||
'indent': @indent
|
||||
'indent-selected-rows': @indentSelectedRows
|
||||
'outdent-selected-rows': @outdentSelectedRows
|
||||
'backspace': @backspace
|
||||
'backspace-to-beginning-of-word': @backspaceToBeginningOfWord
|
||||
'delete': @delete
|
||||
'delete-to-end-of-word': @deleteToEndOfWord
|
||||
'delete-line': @deleteLine
|
||||
'cut-to-end-of-line': @cutToEndOfLine
|
||||
'cut': @cutSelection
|
||||
'copy': @copySelection
|
||||
'paste': @paste
|
||||
'undo': @undo
|
||||
'redo': @redo
|
||||
'move-to-top': @moveCursorToTop
|
||||
'move-to-bottom': @moveCursorToBottom
|
||||
'move-to-beginning-of-line': @moveCursorToBeginningOfLine
|
||||
'move-to-end-of-line': @moveCursorToEndOfLine
|
||||
'move-to-first-character-of-line': @moveCursorToFirstCharacterOfLine
|
||||
'move-to-beginning-of-word': @moveCursorToBeginningOfWord
|
||||
'move-to-end-of-word': @moveCursorToEndOfWord
|
||||
'select-to-top': @selectToTop
|
||||
'select-to-bottom': @selectToBottom
|
||||
'select-to-end-of-line': @selectToEndOfLine
|
||||
'select-to-beginning-of-line': @selectToBeginningOfLine
|
||||
'select-to-end-of-word': @selectToEndOfWord
|
||||
'select-to-beginning-of-word': @selectToBeginningOfWord
|
||||
'select-all': @selectAll
|
||||
'page-down': @pageDown
|
||||
'page-up': @pageUp
|
||||
'core:move-left': @moveCursorLeft
|
||||
'core:move-right': @moveCursorRight
|
||||
'core:move-to-top': @moveCursorToTop
|
||||
'core:move-to-bottom': @moveCursorToBottom
|
||||
'core:page-down': @pageDown
|
||||
'core:page-up': @pageUp
|
||||
'core:select-up': @selectUp
|
||||
'core:select-down': @selectDown
|
||||
'core:select-left': @selectLeft
|
||||
'core:select-right': @selectRight
|
||||
'core:select-to-top': @selectToTop
|
||||
'core:select-to-bottom': @selectToBottom
|
||||
'core:select-all': @selectAll
|
||||
'core:backspace': @backspace
|
||||
'core:delete': @delete
|
||||
'core:undo': @undo
|
||||
'core:redo': @redo
|
||||
'core:cut': @cutSelection
|
||||
'core:copy': @copySelection
|
||||
'core:paste': @paste
|
||||
'editor:move-to-next-word': @moveCursorToNextWord
|
||||
'editor:move-to-previous-word': @moveCursorToPreviousWord
|
||||
'editor:select-word': @selectWord
|
||||
'editor:newline': @insertNewline
|
||||
'editor:indent': @indent
|
||||
'editor:indent-selected-rows': @indentSelectedRows
|
||||
'editor:outdent-selected-rows': @outdentSelectedRows
|
||||
'editor:backspace-to-beginning-of-word': @backspaceToBeginningOfWord
|
||||
'editor:delete-to-end-of-word': @deleteToEndOfWord
|
||||
'editor:delete-line': @deleteLine
|
||||
'editor:cut-to-end-of-line': @cutToEndOfLine
|
||||
'editor:move-to-beginning-of-line': @moveCursorToBeginningOfLine
|
||||
'editor:move-to-end-of-line': @moveCursorToEndOfLine
|
||||
'editor:move-to-first-character-of-line': @moveCursorToFirstCharacterOfLine
|
||||
'editor:move-to-beginning-of-word': @moveCursorToBeginningOfWord
|
||||
'editor:move-to-end-of-word': @moveCursorToEndOfWord
|
||||
'editor:select-to-end-of-line': @selectToEndOfLine
|
||||
'editor:select-to-beginning-of-line': @selectToBeginningOfLine
|
||||
'editor:select-to-end-of-word': @selectToEndOfWord
|
||||
'editor:select-to-beginning-of-word': @selectToBeginningOfWord
|
||||
|
||||
unless @mini
|
||||
_.extend editorBindings,
|
||||
'save': @save
|
||||
'newline-below': @insertNewlineBelow
|
||||
'toggle-soft-wrap': @toggleSoftWrap
|
||||
'fold-all': @foldAll
|
||||
'unfold-all': @unfoldAll
|
||||
'fold-current-row': @foldCurrentRow
|
||||
'unfold-current-row': @unfoldCurrentRow
|
||||
'fold-selection': @foldSelection
|
||||
'split-left': @splitLeft
|
||||
'split-right': @splitRight
|
||||
'split-up': @splitUp
|
||||
'split-down': @splitDown
|
||||
'close': @close
|
||||
'show-next-buffer': @loadNextEditSession
|
||||
'show-previous-buffer': @loadPreviousEditSession
|
||||
'toggle-line-comments': @toggleLineCommentsInSelection
|
||||
'log-cursor-scope': @logCursorScope
|
||||
'core:move-up': @moveCursorUp
|
||||
'core:move-down': @moveCursorDown
|
||||
'core:close': @close
|
||||
'editor:save': @save
|
||||
'editor:newline-below': @insertNewlineBelow
|
||||
'editor:toggle-soft-wrap': @toggleSoftWrap
|
||||
'editor:fold-all': @foldAll
|
||||
'editor:unfold-all': @unfoldAll
|
||||
'editor:fold-current-row': @foldCurrentRow
|
||||
'editor:unfold-current-row': @unfoldCurrentRow
|
||||
'editor:fold-selection': @foldSelection
|
||||
'editor:split-left': @splitLeft
|
||||
'editor:split-right': @splitRight
|
||||
'editor:split-up': @splitUp
|
||||
'editor:split-down': @splitDown
|
||||
'editor:show-next-buffer': @loadNextEditSession
|
||||
'editor:show-previous-buffer': @loadPreviousEditSession
|
||||
'editor:toggle-line-comments': @toggleLineCommentsInSelection
|
||||
'editor:log-cursor-scope': @logCursorScope
|
||||
|
||||
for name, method of editorBindings
|
||||
do (name, method) =>
|
||||
@ -343,6 +343,9 @@ class Editor extends View
|
||||
else
|
||||
@gutter.addClass('drop-shadow')
|
||||
|
||||
@on 'cursor-move', => @highlightCursorLine()
|
||||
@on 'selection-change', => @highlightCursorLine()
|
||||
|
||||
selectOnMousemoveUntilMouseup: ->
|
||||
moveHandler = (e) => @selectToScreenPosition(@screenPositionFromMouseEvent(e))
|
||||
@on 'mousemove', moveHandler
|
||||
@ -415,6 +418,9 @@ class Editor extends View
|
||||
@activeEditSession.on "buffer-path-change", =>
|
||||
@trigger 'editor-path-change'
|
||||
|
||||
@activeEditSession.getSelection().on 'change-screen-range', =>
|
||||
@trigger 'selection-change'
|
||||
|
||||
@trigger 'editor-path-change'
|
||||
@renderWhenAttached()
|
||||
|
||||
@ -640,7 +646,7 @@ class Editor extends View
|
||||
addCursorView: (cursor) ->
|
||||
cursorView = new CursorView(cursor, this)
|
||||
@cursorViews.push(cursorView)
|
||||
@renderedLines.append(cursorView)
|
||||
@appendToLinesView(cursorView)
|
||||
cursorView
|
||||
|
||||
removeCursorView: (cursorView) ->
|
||||
@ -664,7 +670,7 @@ class Editor extends View
|
||||
addSelectionView: (selection) ->
|
||||
selectionView = new SelectionView({editor: this, selection})
|
||||
@selectionViews.push(selectionView)
|
||||
@renderedLines.append(selectionView)
|
||||
@appendToLinesView(selectionView)
|
||||
selectionView
|
||||
|
||||
removeSelectionView: (selectionView) ->
|
||||
@ -674,9 +680,12 @@ class Editor extends View
|
||||
cursorView.remove() for cursorView in @getCursorViews()
|
||||
selectionView.remove() for selectionView in @getSelectionViews()
|
||||
|
||||
appendToLinesView: (view) ->
|
||||
@renderedLines.append(view)
|
||||
|
||||
calculateDimensions: ->
|
||||
fragment = $('<pre class="line" style="position: absolute; visibility: hidden;"><span>x</span></div>')
|
||||
@renderedLines.append(fragment)
|
||||
@appendToLinesView(fragment)
|
||||
|
||||
lineRect = fragment[0].getBoundingClientRect()
|
||||
charRect = fragment.find('span')[0].getBoundingClientRect()
|
||||
@ -746,6 +755,7 @@ class Editor extends View
|
||||
|
||||
if renderedLines
|
||||
@gutter.renderLineNumbers(renderFrom, renderTo)
|
||||
@highlightCursorLine()
|
||||
@updatePaddingOfRenderedLines()
|
||||
|
||||
updatePaddingOfRenderedLines: ->
|
||||
@ -809,11 +819,21 @@ class Editor extends View
|
||||
charHeight = @charHeight
|
||||
lines = @activeEditSession.linesForScreenRows(startRow, endRow)
|
||||
activeEditSession = @activeEditSession
|
||||
cursorScreenRow = @getCursorScreenPosition().row
|
||||
mini = @mini
|
||||
|
||||
buildLineHtml = (line) => @buildLineHtml(line)
|
||||
$$ -> @raw(buildLineHtml(line)) for line in lines
|
||||
buildLineHtml = (line, lineClasses) => @buildLineHtml(line, lineClasses)
|
||||
$$ ->
|
||||
row = startRow
|
||||
for line in lines
|
||||
if mini or row isnt cursorScreenRow
|
||||
lineClasses = null
|
||||
else
|
||||
lineClasses = ' cursor-line'
|
||||
@raw(buildLineHtml(line, lineClasses))
|
||||
row++
|
||||
|
||||
buildLineHtml: (screenLine) ->
|
||||
buildLineHtml: (screenLine, lineClasses) ->
|
||||
scopeStack = []
|
||||
line = []
|
||||
|
||||
@ -845,6 +865,8 @@ class Editor extends View
|
||||
else
|
||||
lineAttributes = { class: 'line' }
|
||||
|
||||
lineAttributes.class += lineClasses if lineClasses
|
||||
|
||||
attributePairs = []
|
||||
attributePairs.push "#{attributeName}=\"#{value}\"" for attributeName, value of lineAttributes
|
||||
line.push("<pre #{attributePairs.join(' ')}>")
|
||||
@ -932,3 +954,12 @@ class Editor extends View
|
||||
@screenPositionFromPixelPosition
|
||||
top: pageY - @scrollView.offset().top + @scrollTop()
|
||||
left: pageX - @scrollView.offset().left + @scrollView.scrollLeft()
|
||||
|
||||
highlightCursorLine: ->
|
||||
return if @mini
|
||||
|
||||
@cursorScreenRow = @getCursorScreenPosition().row
|
||||
screenRow = @cursorScreenRow - @firstRenderedScreenRow
|
||||
@find('pre.line.cursor-line').removeClass('cursor-line')
|
||||
if @getSelection().isSingleScreenLine()
|
||||
@find("pre.line:eq(#{screenRow})").addClass('cursor-line')
|
||||
|
@ -1,4 +1,4 @@
|
||||
{View, $$$} = require 'space-pen'
|
||||
{View, $$, $$$} = require 'space-pen'
|
||||
|
||||
$ = require 'jquery'
|
||||
_ = require 'underscore'
|
||||
@ -9,47 +9,64 @@ class Gutter extends View
|
||||
@div class: 'gutter', =>
|
||||
@div outlet: 'lineNumbers', class: 'line-numbers'
|
||||
|
||||
cursorBufferRow: -1
|
||||
firstScreenRow: -1
|
||||
highestNumberWidth: null
|
||||
|
||||
afterAttach: (onDom) ->
|
||||
@editor()?.on 'cursor-move', => @highlightCursorLine()
|
||||
return if @attached or not onDom
|
||||
@attached = true
|
||||
|
||||
editor = @editor()
|
||||
highlightCursorLine = => @highlightCursorLine()
|
||||
editor.on 'cursor-move', highlightCursorLine
|
||||
editor.on 'selection-change', highlightCursorLine
|
||||
@calculateWidth()
|
||||
|
||||
editor: ->
|
||||
@parentView
|
||||
|
||||
calculateLineNumberPadding: ->
|
||||
widthTesterElement = $$ -> @div {class: 'line-number'}, ""
|
||||
widthTesterElement.width(0)
|
||||
@append(widthTesterElement)
|
||||
lineNumberPadding = widthTesterElement.outerWidth()
|
||||
widthTesterElement.remove()
|
||||
lineNumberPadding
|
||||
|
||||
renderLineNumbers: (startScreenRow, endScreenRow) ->
|
||||
@firstScreenRow = startScreenRow
|
||||
lastScreenRow = -1
|
||||
currentCursorBufferRow = @cursorBufferRow
|
||||
rows = @editor().bufferRowsForScreenRows(startScreenRow, endScreenRow)
|
||||
|
||||
cursorScreenRow = @editor().getCursorScreenPosition().row
|
||||
@lineNumbers[0].innerHTML = $$$ ->
|
||||
for row in rows
|
||||
rowClass = null
|
||||
if row isnt currentCursorBufferRow
|
||||
rowClass = 'line-number'
|
||||
if row == lastScreenRow
|
||||
rowValue = '•'
|
||||
else
|
||||
rowClass = 'line-number cursor-line-number'
|
||||
@div {class: rowClass}, if row == lastScreenRow then '•' else row + 1
|
||||
rowValue = row + 1
|
||||
@div {class: 'line-number'}, rowValue
|
||||
lastScreenRow = row
|
||||
|
||||
@calculateWidth()
|
||||
@highlightCursorLine()
|
||||
|
||||
calculateWidth: ->
|
||||
width = @editor().getLineCount().toString().length * @editor().charWidth
|
||||
if width != @cachedWidth
|
||||
@cachedWidth = width
|
||||
@lineNumbers.width(width)
|
||||
highestNumberWidth = @editor().getLineCount().toString().length * @editor().charWidth
|
||||
if highestNumberWidth != @highestNumberWidth
|
||||
@highestNumberWidth = highestNumberWidth
|
||||
@lineNumbers.width(highestNumberWidth + @calculateLineNumberPadding())
|
||||
@widthChanged?(@outerWidth())
|
||||
|
||||
highlightCursorLine: ->
|
||||
return if @firstScreenRow < 0
|
||||
cursorScreenRow = @editor().getCursorScreenPosition().row
|
||||
screenRowIndex = cursorScreenRow - @firstScreenRow
|
||||
|
||||
newCursorBufferRow = @editor().getCursorBufferPosition().row
|
||||
if newCursorBufferRow isnt @cursorBufferRow
|
||||
@cursorBufferRow = newCursorBufferRow
|
||||
screenRow = @cursorBufferRow - @firstScreenRow
|
||||
@find('.line-number.cursor-line-number').removeClass('cursor-line-number')
|
||||
@find(".line-number:eq(#{screenRow})").addClass('cursor-line-number')
|
||||
currentLineNumberRow = @find(".line-number.cursor-line-number")
|
||||
currentLineNumberRow.removeClass('cursor-line-number')
|
||||
currentLineNumberRow.removeClass('cursor-line-number-background')
|
||||
|
||||
newLineNumberRow = @find(".line-number:eq(#{screenRowIndex})")
|
||||
newLineNumberRow.addClass('cursor-line-number')
|
||||
if @editor().getSelection().isSingleScreenLine()
|
||||
newLineNumberRow.addClass('cursor-line-number-background')
|
||||
|
@ -1,15 +1,17 @@
|
||||
window.keymap.bindKeys 'body'
|
||||
'meta-up': 'core:move-to-top'
|
||||
'meta-down': 'core:move-to-bottom'
|
||||
'meta-shift-up': 'core:select-to-top'
|
||||
'meta-shift-down': 'core:select-to-bottom'
|
||||
|
||||
window.keymap.bindKeys '.editor'
|
||||
'meta-up': 'move-to-top'
|
||||
'meta-down': 'move-to-bottom'
|
||||
'meta-right': 'move-to-end-of-line'
|
||||
'meta-left': 'move-to-beginning-of-line'
|
||||
'alt-left': 'move-to-beginning-of-word'
|
||||
'alt-right': 'move-to-end-of-word'
|
||||
'meta-shift-up': 'select-to-top'
|
||||
'meta-shift-down': 'select-to-bottom'
|
||||
'meta-shift-left': 'select-to-beginning-of-line'
|
||||
'meta-shift-right': 'select-to-end-of-line'
|
||||
'alt-shift-left': 'select-to-beginning-of-word'
|
||||
'alt-shift-right': 'select-to-end-of-word'
|
||||
'alt-backspace': 'backspace-to-beginning-of-word'
|
||||
'alt-delete': 'delete-to-end-of-word'
|
||||
'meta-right': 'editor:move-to-end-of-line'
|
||||
'meta-left': 'editor:move-to-beginning-of-line'
|
||||
'alt-left': 'editor:move-to-beginning-of-word'
|
||||
'alt-right': 'editor:move-to-end-of-word'
|
||||
'meta-shift-left': 'editor:select-to-beginning-of-line'
|
||||
'meta-shift-right': 'editor:select-to-end-of-line'
|
||||
'alt-shift-left': 'editor:select-to-beginning-of-word'
|
||||
'alt-shift-right': 'editor:select-to-end-of-word'
|
||||
'alt-backspace': 'editor:backspace-to-beginning-of-word'
|
||||
'alt-delete': 'editor:delete-to-end-of-word'
|
||||
|
@ -1,10 +1,27 @@
|
||||
window.keymap.bindKeys '*'
|
||||
'meta-w': 'close'
|
||||
window.keymap.bindKeys 'body'
|
||||
'alt-meta-i': 'toggle-dev-tools'
|
||||
right: 'move-right'
|
||||
left: 'move-left'
|
||||
down: 'move-down'
|
||||
up: 'move-up'
|
||||
pagedown: 'page-down'
|
||||
pageup: 'page-up'
|
||||
'meta-S': 'save-all'
|
||||
'meta-w': 'core:close'
|
||||
up: 'core:move-up'
|
||||
down: 'core:move-down'
|
||||
left: 'core:move-left'
|
||||
right: 'core:move-right'
|
||||
'shift-up': 'core:select-up'
|
||||
'shift-down': 'core:select-down'
|
||||
'shift-left': 'core:select-left'
|
||||
'shift-right': 'core:select-right'
|
||||
'meta-a': 'core:select-all'
|
||||
'backspace': 'core:backspace'
|
||||
'shift-backspace': 'core:backspace'
|
||||
'delete': 'core:delete'
|
||||
'meta-z': 'core:undo'
|
||||
'meta-Z': 'core:redo'
|
||||
'meta-x': 'core:cut'
|
||||
'meta-c': 'core:copy'
|
||||
'meta-v': 'core:paste'
|
||||
pageup: 'core:page-up'
|
||||
pagedown: 'core:page-down'
|
||||
|
||||
'meta-S': 'root-view:save-all'
|
||||
'meta-+': 'root-view:increase-font-size'
|
||||
'meta--': 'root-view:decrease-font-size'
|
||||
'ctrl-w w': 'root-view:focus-next-pane'
|
||||
|
@ -1,40 +1,25 @@
|
||||
window.keymap.bindKeys '.editor',
|
||||
'meta-s': 'save'
|
||||
'shift-right': 'select-right'
|
||||
'shift-left': 'select-left'
|
||||
'shift-up': 'select-up'
|
||||
'shift-down': 'select-down'
|
||||
'meta-a': 'select-all'
|
||||
'enter': 'newline'
|
||||
'meta-enter': 'newline-below'
|
||||
'tab': 'indent'
|
||||
'backspace': 'backspace'
|
||||
'shift-backspace': 'backspace'
|
||||
'delete': 'delete'
|
||||
'meta-d': 'delete-line'
|
||||
'meta-x': 'cut'
|
||||
'meta-c': 'copy'
|
||||
'meta-v': 'paste'
|
||||
'meta-z': 'undo'
|
||||
'meta-Z': 'redo'
|
||||
'alt-meta-w': 'toggle-soft-wrap'
|
||||
'ctrl-[': 'fold-current-row'
|
||||
'ctrl-]': 'unfold-current-row'
|
||||
'ctrl-{': 'fold-all'
|
||||
'ctrl-}': 'unfold-all'
|
||||
'alt-meta-ctrl-f': 'fold-selection'
|
||||
'alt-meta-left': 'split-left'
|
||||
'alt-meta-right': 'split-right'
|
||||
'alt-meta-up': 'split-up'
|
||||
'alt-meta-down': 'split-down'
|
||||
'shift-tab': 'outdent-selected-rows'
|
||||
'meta-[': 'outdent-selected-rows'
|
||||
'meta-]': 'indent-selected-rows'
|
||||
'meta-{': 'show-previous-buffer'
|
||||
'meta-}': 'show-next-buffer'
|
||||
'meta-+': 'increase-font-size'
|
||||
'meta--': 'decrease-font-size'
|
||||
'meta-/': 'toggle-line-comments'
|
||||
'ctrl-w w': 'focus-next-pane'
|
||||
'ctrl-W': 'select-word'
|
||||
'meta-alt-p': 'log-cursor-scope'
|
||||
'meta-s': 'editor:save'
|
||||
'enter': 'editor:newline'
|
||||
'meta-enter': 'editor:newline-below'
|
||||
'tab': 'editor:indent'
|
||||
'meta-d': 'editor:delete-line'
|
||||
'alt-meta-w': 'editor:toggle-soft-wrap'
|
||||
'ctrl-[': 'editor:fold-current-row'
|
||||
'ctrl-]': 'editor:unfold-current-row'
|
||||
'ctrl-{': 'editor:fold-all'
|
||||
'ctrl-}': 'editor:unfold-all'
|
||||
'alt-meta-ctrl-f': 'editor:fold-selection'
|
||||
'alt-meta-left': 'editor:split-left'
|
||||
'alt-meta-right': 'editor:split-right'
|
||||
'alt-meta-up': 'editor:split-up'
|
||||
'alt-meta-down': 'editor:split-down'
|
||||
'shift-tab': 'editor:outdent-selected-rows'
|
||||
'meta-[': 'editor:outdent-selected-rows'
|
||||
'meta-]': 'editor:indent-selected-rows'
|
||||
'meta-{': 'editor:show-previous-buffer'
|
||||
'meta-}': 'editor:show-next-buffer'
|
||||
'meta-/': 'editor:toggle-line-comments'
|
||||
'ctrl-W': 'editor:select-word'
|
||||
'meta-alt-p': 'editor:log-cursor-scope'
|
||||
|
||||
|
@ -1,22 +1,22 @@
|
||||
window.keymap.bindKeys '*',
|
||||
'ctrl-f': 'move-right'
|
||||
'ctrl-b': 'move-left'
|
||||
'ctrl-p': 'move-up'
|
||||
'ctrl-n': 'move-down'
|
||||
window.keymap.bindKeys 'body',
|
||||
'ctrl-p': 'core:move-up'
|
||||
'ctrl-n': 'core:move-down'
|
||||
'ctrl-b': 'core:move-left'
|
||||
'ctrl-f': 'core:move-right'
|
||||
'ctrl-P': 'core:select-up'
|
||||
'ctrl-N': 'core:select-down'
|
||||
'ctrl-F': 'core:select-right'
|
||||
'ctrl-B': 'core:select-left'
|
||||
'ctrl-h': 'core:backspace'
|
||||
'ctrl-d': 'core:delete'
|
||||
|
||||
window.keymap.bindKeys '.editor',
|
||||
'ctrl-F': 'select-right'
|
||||
'ctrl-B': 'select-left'
|
||||
'ctrl-P': 'select-up'
|
||||
'ctrl-N': 'select-down'
|
||||
'alt-f': 'move-to-end-of-word'
|
||||
'alt-F': 'select-to-end-of-word'
|
||||
'alt-b': 'move-to-beginning-of-word'
|
||||
'alt-B': 'select-to-beginning-of-word'
|
||||
'ctrl-a': 'move-to-first-character-of-line'
|
||||
'ctrl-e': 'move-to-end-of-line'
|
||||
'ctrl-h': 'backspace'
|
||||
'ctrl-d': 'delete'
|
||||
'alt-h': 'backspace-to-beginning-of-word'
|
||||
'alt-d': 'delete-to-end-of-word'
|
||||
'ctrl-k': 'cut-to-end-of-line'
|
||||
'alt-f': 'editor:move-to-end-of-word'
|
||||
'alt-F': 'editor:select-to-end-of-word'
|
||||
'alt-b': 'editor:move-to-beginning-of-word'
|
||||
'alt-B': 'editor:select-to-beginning-of-word'
|
||||
'ctrl-a': 'editor:move-to-first-character-of-line'
|
||||
'ctrl-e': 'editor:move-to-end-of-line'
|
||||
'alt-h': 'editor:backspace-to-beginning-of-word'
|
||||
'alt-d': 'editor:delete-to-end-of-word'
|
||||
'ctrl-k': 'editor:cut-to-end-of-line'
|
||||
|
@ -49,7 +49,9 @@ class LanguageMode
|
||||
scopes = @tokenizedBuffer.scopesForPosition(range.start)
|
||||
return unless commentString = TextMateBundle.lineCommentStringForScope(scopes[0])
|
||||
|
||||
commentRegex = new OnigRegExp("^\s*" + _.escapeRegExp(commentString))
|
||||
commentRegexString = _.escapeRegExp(commentString)
|
||||
commentRegexString = commentRegexString.replace(/(\s+)$/, '($1)?')
|
||||
commentRegex = new OnigRegExp("^\s*#{commentRegexString}")
|
||||
|
||||
shouldUncomment = commentRegex.test(@editSession.lineForBufferRow(range.start.row))
|
||||
|
||||
|
@ -73,10 +73,10 @@ class RootView extends View
|
||||
@project.setPath(path) unless @project.getRootDirectory()
|
||||
@setTitle(path)
|
||||
|
||||
@on 'increase-font-size', => @setFontSize(@getFontSize() + 1)
|
||||
@on 'decrease-font-size', => @setFontSize(@getFontSize() - 1)
|
||||
@on 'focus-next-pane', => @focusNextPane()
|
||||
@on 'save-all', => @saveAll()
|
||||
@on 'root-view:increase-font-size', => @setFontSize(@getFontSize() + 1)
|
||||
@on 'root-view:decrease-font-size', => @setFontSize(@getFontSize() - 1)
|
||||
@on 'root-view:focus-next-pane', => @focusNextPane()
|
||||
@on 'root-view:save-all', => @saveAll()
|
||||
|
||||
afterAttach: (onDom) ->
|
||||
@focus() if onDom
|
||||
|
@ -31,6 +31,9 @@ class Selection
|
||||
isReversed: ->
|
||||
not @isEmpty() and @cursor.getBufferPosition().isLessThan(@anchor.getBufferPosition())
|
||||
|
||||
isSingleScreenLine: ->
|
||||
@getScreenRange().isSingleLine()
|
||||
|
||||
getScreenRange: ->
|
||||
if @anchor
|
||||
new Range(@anchor.getScreenPosition(), @cursor.getScreenPosition())
|
||||
|
@ -54,13 +54,15 @@ class Autocomplete extends View
|
||||
@cancel()
|
||||
|
||||
@miniEditor.getBuffer().on 'change', (e) =>
|
||||
@filterMatches() if @hasParent()
|
||||
if @hasParent()
|
||||
@filterMatches()
|
||||
@renderMatchList()
|
||||
|
||||
@miniEditor.preempt 'move-up', =>
|
||||
@miniEditor.preempt 'core:move-up', =>
|
||||
@selectPreviousMatch()
|
||||
false
|
||||
|
||||
@miniEditor.preempt 'move-down', =>
|
||||
@miniEditor.preempt 'core:move-down', =>
|
||||
@selectNextMatch()
|
||||
false
|
||||
|
||||
@ -110,10 +112,16 @@ class Autocomplete extends View
|
||||
|
||||
originalCursorPosition = @editor.getCursorScreenPosition()
|
||||
@filterMatches()
|
||||
@editor.append(this)
|
||||
@setPosition(originalCursorPosition)
|
||||
|
||||
@miniEditor.focus()
|
||||
if @filteredMatches.length is 1
|
||||
@currentMatchIndex = 0
|
||||
@replaceSelectedTextWithMatch @selectedMatch()
|
||||
@confirm()
|
||||
else
|
||||
@renderMatchList()
|
||||
@editor.appendToLinesView(this)
|
||||
@setPosition(originalCursorPosition)
|
||||
@miniEditor.focus()
|
||||
|
||||
detach: ->
|
||||
@miniEditor.off("focusout")
|
||||
@ -125,12 +133,12 @@ class Autocomplete extends View
|
||||
setPosition: (originalCursorPosition) ->
|
||||
{ left, top } = @editor.pixelPositionForScreenPosition(originalCursorPosition)
|
||||
|
||||
top -= @editor.scrollTop()
|
||||
height = @outerHeight()
|
||||
potentialTop = top + @editor.lineHeight
|
||||
potentialBottom = potentialTop + @outerHeight()
|
||||
potentialBottom = potentialTop - @editor.scrollTop() + height
|
||||
|
||||
if potentialBottom > @editor.outerHeight()
|
||||
@css(left: left, bottom: @editor.outerHeight() - top, top: 'inherit')
|
||||
@css(left: left, top: top - height, bottom: 'inherit')
|
||||
else
|
||||
@css(left: left, top: potentialTop, bottom: 'inherit')
|
||||
|
||||
@ -166,7 +174,6 @@ class Autocomplete extends View
|
||||
|
||||
filterMatches: ->
|
||||
@filteredMatches = fuzzyFilter(@allMatches, @miniEditor.getText(), key: 'word')
|
||||
@renderMatchList()
|
||||
|
||||
renderMatchList: ->
|
||||
@matchesList.empty()
|
||||
|
@ -62,9 +62,8 @@ class CommandPanel extends View
|
||||
@rootView.on 'command-panel:repeat-relative-address-in-reverse', => @repeatRelativeAddressInReverse()
|
||||
@rootView.on 'command-panel:set-selection-as-regex-address', => @setSelectionAsLastRelativeAddress()
|
||||
|
||||
@miniEditor.off 'move-up move-down'
|
||||
@miniEditor.on 'move-up', => @navigateBackwardInHistory()
|
||||
@miniEditor.on 'move-down', => @navigateForwardInHistory()
|
||||
@on 'core:move-up', => @navigateBackwardInHistory()
|
||||
@on 'core:move-down', => @navigateForwardInHistory()
|
||||
|
||||
@previewList.hide()
|
||||
|
||||
|
@ -10,8 +10,8 @@ class PreviewList extends View
|
||||
operations: null
|
||||
|
||||
initialize: (@rootView) ->
|
||||
@on 'move-down', => @selectNextOperation()
|
||||
@on 'move-up', => @selectPreviousOperation()
|
||||
@on 'core:move-down', => @selectNextOperation()
|
||||
@on 'core:move-up', => @selectPreviousOperation()
|
||||
@on 'command-panel:execute', => @executeSelectedOperation()
|
||||
|
||||
@on 'mousedown', 'li', (e) =>
|
||||
|
@ -26,13 +26,13 @@ class FuzzyFinder extends View
|
||||
@rootView.on 'fuzzy-finder:toggle-buffer-finder', => @toggleBufferFinder()
|
||||
|
||||
@on 'fuzzy-finder:cancel', => @detach()
|
||||
@on 'move-up', => @moveUp()
|
||||
@on 'move-down', => @moveDown()
|
||||
@on 'core:move-up', => @moveUp()
|
||||
@on 'core:move-down', => @moveDown()
|
||||
@on 'fuzzy-finder:select-path', => @select()
|
||||
@on 'mousedown', 'li', (e) => @entryClicked(e)
|
||||
|
||||
@miniEditor.getBuffer().on 'change', => @populatePathList() if @hasParent()
|
||||
@miniEditor.off 'move-up move-down'
|
||||
@miniEditor.off 'core:move-up core:move-down'
|
||||
|
||||
toggleFileFinder: ->
|
||||
if @hasParent()
|
||||
@ -93,18 +93,22 @@ class FuzzyFinder extends View
|
||||
false
|
||||
|
||||
moveUp: ->
|
||||
@findSelectedLi()
|
||||
.filter(':not(:first-child)')
|
||||
.removeClass('selected')
|
||||
.prev()
|
||||
.addClass('selected')
|
||||
selected = @findSelectedLi().removeClass('selected')
|
||||
|
||||
if selected.filter(':not(:first-child)').length is 0
|
||||
selected = @pathList.children('li:last')
|
||||
else
|
||||
selected = selected.prev()
|
||||
selected.addClass('selected')
|
||||
|
||||
moveDown: ->
|
||||
@findSelectedLi()
|
||||
.filter(':not(:last-child)')
|
||||
.removeClass('selected')
|
||||
.next()
|
||||
.addClass('selected')
|
||||
selected = @findSelectedLi().removeClass('selected')
|
||||
|
||||
if selected.filter(':not(:last-child)').length is 0
|
||||
selected = @pathList.children('li:first')
|
||||
else
|
||||
selected = selected.next()
|
||||
selected.addClass('selected')
|
||||
|
||||
findMatches: (query) ->
|
||||
fuzzyFilter(@paths, query, maxResults: @maxResults)
|
||||
|
@ -1,4 +1,4 @@
|
||||
{View, $$} = require 'space-pen'
|
||||
{View} = require 'space-pen'
|
||||
fs = require 'fs'
|
||||
$ = require 'jquery'
|
||||
|
||||
|
@ -12,7 +12,7 @@ class Dialog extends View
|
||||
|
||||
initialize: ({path, @onConfirm, select} = {}) ->
|
||||
@miniEditor.focus()
|
||||
@on 'tree-view:confirm', => @confirm()
|
||||
@on 'tree-view:confirm', => @onConfirm(@miniEditor.getText())
|
||||
@on 'tree-view:cancel', => @cancel()
|
||||
@miniEditor.on 'focusout', => @remove()
|
||||
|
||||
@ -24,8 +24,7 @@ class Dialog extends View
|
||||
range = [[0, path.length - baseName.length], [0, path.length - extension.length]]
|
||||
@miniEditor.setSelectedBufferRange(range)
|
||||
|
||||
confirm: ->
|
||||
return if @onConfirm(@miniEditor.getText()) is false
|
||||
close: ->
|
||||
@remove()
|
||||
$('#root-view').focus()
|
||||
|
||||
|
@ -42,18 +42,27 @@ class TreeView extends View
|
||||
root: null
|
||||
focusAfterAttach: false
|
||||
scrollTopAfterAttach: -1
|
||||
selectedPath: null
|
||||
|
||||
initialize: (@rootView) ->
|
||||
@on 'click', '.entry', (e) => @entryClicked(e)
|
||||
@on 'move-up', => @moveUp()
|
||||
@on 'move-down', => @moveDown()
|
||||
@on 'core:move-up', => @moveUp()
|
||||
@on 'core:move-down', => @moveDown()
|
||||
@on 'core:move-to-top', => @scrollToTop()
|
||||
@on 'core:move-to-bottom', => @scrollToBottom()
|
||||
@on 'core:page-up', => @pageUp()
|
||||
@on 'core:page-down', => @pageDown()
|
||||
@on 'tree-view:expand-directory', => @expandDirectory()
|
||||
@on 'tree-view:collapse-directory', => @collapseDirectory()
|
||||
@on 'tree-view:open-selected-entry', => @openSelectedEntry(true)
|
||||
@on 'tree-view:move', => @moveSelectedEntry()
|
||||
@on 'tree-view:add', => @add()
|
||||
@on 'tree-view:remove', => @removeSelectedEntry()
|
||||
@on 'tree-view:directory-modified', => @selectActiveFile()
|
||||
@on 'tree-view:directory-modified', =>
|
||||
if @hasFocus()
|
||||
@selectEntryForPath(@selectedPath) if @selectedPath
|
||||
else
|
||||
@selectActiveFile()
|
||||
@on 'tree-view:unfocus', => @rootView.focus()
|
||||
@rootView.on 'tree-view:toggle', => @toggle()
|
||||
@rootView.on 'tree-view:reveal-active-file', => @revealActiveFile()
|
||||
@ -69,7 +78,7 @@ class TreeView extends View
|
||||
serialize: ->
|
||||
directoryExpansionStates: @root?.serializeEntryExpansionStates()
|
||||
selectedPath: @selectedEntry()?.getPath()
|
||||
hasFocus: @is(':focus')
|
||||
hasFocus: @hasFocus()
|
||||
attached: @hasParent()
|
||||
scrollTop: @scrollTop()
|
||||
|
||||
@ -77,7 +86,7 @@ class TreeView extends View
|
||||
@root?.unwatchEntries()
|
||||
|
||||
toggle: ->
|
||||
if @is(':focus')
|
||||
if @hasFocus()
|
||||
@detach()
|
||||
@rootView.focus()
|
||||
else
|
||||
@ -91,6 +100,9 @@ class TreeView extends View
|
||||
@scrollTopAfterAttach = @scrollTop()
|
||||
super
|
||||
|
||||
hasFocus: ->
|
||||
@is(':focus')
|
||||
|
||||
entryClicked: (e) ->
|
||||
entry = $(e.currentTarget).view()
|
||||
switch e.originalEvent?.detail ? 1
|
||||
@ -194,7 +206,7 @@ class TreeView extends View
|
||||
moveSelectedEntry: ->
|
||||
entry = @selectedEntry()
|
||||
return unless entry
|
||||
oldPath = @selectedEntry().getPath()
|
||||
oldPath = entry.getPath()
|
||||
|
||||
dialog = new Dialog
|
||||
prompt: "Enter the new path for the file:"
|
||||
@ -206,9 +218,9 @@ class TreeView extends View
|
||||
try
|
||||
fs.makeTree(directoryPath) unless fs.exists(directoryPath)
|
||||
fs.move(oldPath, newPath)
|
||||
dialog.close()
|
||||
catch e
|
||||
dialog.showError("Error: " + e.message + " Try a different path:")
|
||||
return false
|
||||
|
||||
@rootView.append(dialog)
|
||||
|
||||
@ -236,21 +248,23 @@ class TreeView extends View
|
||||
path: relativeDirectoryPath
|
||||
select: false
|
||||
onConfirm: (relativePath) =>
|
||||
endsWithDirectorySeperator = /\/$/.test(relativePath)
|
||||
endsWithDirectorySeparator = /\/$/.test(relativePath)
|
||||
path = @rootView.project.resolve(relativePath)
|
||||
try
|
||||
if fs.exists(path)
|
||||
pathType = if fs.isFile(path) then "file" else "directory"
|
||||
dialog.showError("Error: A #{pathType} already exists at path '#{path}'. Try a different path:")
|
||||
false
|
||||
else if endsWithDirectorySeperator
|
||||
else if endsWithDirectorySeparator
|
||||
fs.makeTree(path)
|
||||
dialog.cancel()
|
||||
@entryForPath(path).buildEntries()
|
||||
@selectEntryForPath(path)
|
||||
else
|
||||
fs.write(path, "")
|
||||
@rootView.open(path)
|
||||
dialog.close()
|
||||
catch e
|
||||
dialog.showError("Error: " + e.message + " Try a different path:")
|
||||
return false
|
||||
|
||||
@rootView.append(dialog)
|
||||
|
||||
@ -259,6 +273,8 @@ class TreeView extends View
|
||||
|
||||
selectEntry: (entry) ->
|
||||
return false unless entry.get(0)
|
||||
entry = entry.view() unless entry instanceof View
|
||||
@selectedPath = entry.getPath()
|
||||
@find('.selected').removeClass('selected')
|
||||
entry.addClass('selected')
|
||||
|
||||
|
@ -32,10 +32,10 @@ class VimMode
|
||||
'i': 'insert'
|
||||
'd': 'delete'
|
||||
'x': 'delete-right'
|
||||
'h': 'move-left'
|
||||
'j': 'move-down'
|
||||
'k': 'move-up'
|
||||
'l': 'move-right'
|
||||
'h': 'core:move-left'
|
||||
'j': 'core:move-down'
|
||||
'k': 'core:move-up'
|
||||
'l': 'core:move-right'
|
||||
'w': 'move-to-next-word'
|
||||
'b': 'move-to-previous-word'
|
||||
'}': 'move-to-next-paragraph'
|
||||
@ -47,10 +47,10 @@ class VimMode
|
||||
'insert': => @activateInsertMode()
|
||||
'delete': => @delete()
|
||||
'delete-right': => new commands.DeleteRight(@editor)
|
||||
'move-left': => new motions.MoveLeft(@editor)
|
||||
'move-up': => new motions.MoveUp(@editor)
|
||||
'move-down': => new motions.MoveDown @editor
|
||||
'move-right': => new motions.MoveRight @editor
|
||||
'core:move-left': => new motions.MoveLeft(@editor)
|
||||
'core:move-up': => new motions.MoveUp(@editor)
|
||||
'core:move-down': => new motions.MoveDown @editor
|
||||
'core:move-right': => new motions.MoveRight @editor
|
||||
'move-to-next-word': => new motions.MoveToNextWord(@editor)
|
||||
'move-to-previous-word': => new motions.MoveToPreviousWord(@editor)
|
||||
'move-to-next-paragraph': => new motions.MoveToNextParagraph(@editor)
|
||||
|
@ -6,12 +6,24 @@ $.fn.scrollBottom = (newValue) ->
|
||||
else
|
||||
@scrollTop() + @height()
|
||||
|
||||
$.fn.scrollToTop = ->
|
||||
@scrollTop(0)
|
||||
|
||||
$.fn.scrollToBottom = ->
|
||||
@scrollTop(@prop('scrollHeight'))
|
||||
|
||||
$.fn.scrollRight = (newValue) ->
|
||||
if newValue?
|
||||
@scrollLeft(newValue - @width())
|
||||
else
|
||||
@scrollLeft() + @width()
|
||||
|
||||
$.fn.pageUp = ->
|
||||
@scrollTop(@scrollTop() - @height())
|
||||
|
||||
$.fn.pageDown = ->
|
||||
@scrollTop(@scrollTop() + @height())
|
||||
|
||||
$.fn.containsElement = (element) ->
|
||||
(element[0].compareDocumentPosition(this[0]) & 8) == 8
|
||||
|
||||
|
@ -16,8 +16,6 @@
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
padding-left: 0.4em;
|
||||
padding-right: 0.8em;
|
||||
color: rgba(255, 255, 255, .3);
|
||||
text-align: right;
|
||||
}
|
||||
@ -26,10 +24,19 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.line-number.cursor-line-number {
|
||||
.editor .gutter .line-number {
|
||||
padding-left: 0.4em;
|
||||
padding-right: 0.8em;
|
||||
}
|
||||
|
||||
.editor.focused .line-number.cursor-line-number {
|
||||
color: rgba(255, 255, 255, .6);
|
||||
}
|
||||
|
||||
.editor.focused .line.cursor-line, .editor.focused .line-number.cursor-line-number-background {
|
||||
background-color: rgba(255, 255, 255, .12);
|
||||
}
|
||||
|
||||
.editor.mini .gutter {
|
||||
display: none;
|
||||
}
|
||||
|
@ -65,6 +65,20 @@
|
||||
border-bottom: 1px solid #CCC;
|
||||
}
|
||||
|
||||
.markdown-body h3 {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.markdown-body h4 {
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.markdown-body p {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user