diff --git a/Cargo.lock b/Cargo.lock
index 63aa72410f672fc854c3241257748d6626e7628a..57466fb0f792645f07349ba7bc51675d5924624f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -6051,14 +6051,18 @@ dependencies = [
"anyhow",
"clock",
"collections",
+ "ctor",
+ "env_logger",
"futures 0.3.28",
"git",
"gpui",
+ "itertools 0.11.0",
"language",
"log",
"parking_lot",
"rand 0.8.5",
"settings",
+ "smallvec",
"sum_tree",
"text",
"theme",
diff --git a/assets/icons/LICENSES b/assets/icons/LICENSES
new file mode 100644
index 0000000000000000000000000000000000000000..7a2fc3b8637adf786f3c5366b0215ea54edd8587
--- /dev/null
+++ b/assets/icons/LICENSES
@@ -0,0 +1,9 @@
+Lucide License
+
+ISC License
+
+Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2022.
+
+Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/assets/icons/expand_vertical.svg b/assets/icons/expand_vertical.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e2789114785b85aa33803a0e7b632f81c02642b0
--- /dev/null
+++ b/assets/icons/expand_vertical.svg
@@ -0,0 +1 @@
+
diff --git a/assets/keymaps/default-linux.json b/assets/keymaps/default-linux.json
index e285ef3384cac6a616d9f0dc265842c0d8d7e277..209699b3cd9516663ba870c48df3fd033d80d6e6 100644
--- a/assets/keymaps/default-linux.json
+++ b/assets/keymaps/default-linux.json
@@ -527,6 +527,7 @@
"context": "Editor && mode == full",
"bindings": {
"alt-enter": "editor::OpenExcerpts",
+ "shift-enter": "editor::ExpandExcerpts",
"ctrl-k enter": "editor::OpenExcerptsSplit",
"ctrl-f8": "editor::GoToHunk",
"ctrl-shift-f8": "editor::GoToPrevHunk",
diff --git a/assets/keymaps/default-macos.json b/assets/keymaps/default-macos.json
index 9aaa5776943c5acdceb5c1453d17ecdf1ea4fdeb..f909bd48c50048c1dda4805fd8ebfc942eda9dd1 100644
--- a/assets/keymaps/default-macos.json
+++ b/assets/keymaps/default-macos.json
@@ -541,6 +541,7 @@
"context": "Editor && mode == full",
"bindings": {
"alt-enter": "editor::OpenExcerpts",
+ "shift-enter": "editor::ExpandExcerpts",
"cmd-k enter": "editor::OpenExcerptsSplit",
"cmd-f8": "editor::GoToHunk",
"cmd-shift-f8": "editor::GoToPrevHunk",
diff --git a/crates/editor/src/actions.rs b/crates/editor/src/actions.rs
index a5a3e4fee1c39f8a5e7fa5afd86ef88ef1b97abb..1494c23c00e8eac90ffce944029d771b9890273b 100644
--- a/crates/editor/src/actions.rs
+++ b/crates/editor/src/actions.rs
@@ -94,12 +94,19 @@ pub struct SelectDownByLines {
pub(super) lines: u32,
}
+#[derive(PartialEq, Clone, Deserialize, Default)]
+pub struct ExpandExcerpts {
+ #[serde(default)]
+ pub(super) lines: u32,
+}
+
impl_actions!(
editor,
[
SelectNext,
SelectPrevious,
SelectToBeginningOfLine,
+ ExpandExcerpts,
MovePageUp,
MovePageDown,
SelectToEndOfLine,
@@ -254,6 +261,6 @@ gpui::actions!(
UndoSelection,
UnfoldLines,
UniqueLinesCaseSensitive,
- UniqueLinesCaseInsensitive
+ UniqueLinesCaseInsensitive,
]
);
diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs
index 9605d6842de58132290f387a5f53a6139f7a3c71..3356d507cd1a47032689e7abc5156fdcc4e491e4 100644
--- a/crates/editor/src/editor.rs
+++ b/crates/editor/src/editor.rs
@@ -7462,6 +7462,28 @@ impl Editor {
self.selection_history.mode = SelectionHistoryMode::Normal;
}
+ pub fn expand_excerpts(&mut self, action: &ExpandExcerpts, cx: &mut ViewContext) {
+ let selections = self.selections.disjoint_anchors();
+
+ let lines = if action.lines == 0 { 3 } else { action.lines };
+
+ self.buffer.update(cx, |buffer, cx| {
+ buffer.expand_excerpts(
+ selections
+ .into_iter()
+ .map(|selection| selection.head().excerpt_id)
+ .dedup(),
+ lines,
+ cx,
+ )
+ })
+ }
+
+ pub fn expand_excerpt(&mut self, excerpt: ExcerptId, cx: &mut ViewContext) {
+ self.buffer
+ .update(cx, |buffer, cx| buffer.expand_excerpts([excerpt], 3, cx))
+ }
+
fn go_to_diagnostic(&mut self, _: &GoToDiagnostic, cx: &mut ViewContext) {
self.go_to_diagnostic_impl(Direction::Next, cx)
}
diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs
index b8ee1643c6081699fb715c29cb006ef9de83a013..98837be7b915f56bf2106fa54decf25bbfcfeae6 100644
--- a/crates/editor/src/element.rs
+++ b/crates/editor/src/element.rs
@@ -13,9 +13,9 @@ use crate::{
mouse_context_menu::{self, MouseContextMenu},
scroll::scroll_amount::ScrollAmount,
CursorShape, DisplayPoint, DocumentHighlightRead, DocumentHighlightWrite, Editor, EditorMode,
- EditorSettings, EditorSnapshot, EditorStyle, GutterDimensions, HalfPageDown, HalfPageUp,
- HoveredCursor, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point, SelectPhase, Selection,
- SoftWrap, ToPoint, CURSORS_VISIBLE_FOR, MAX_LINE_LEN,
+ EditorSettings, EditorSnapshot, EditorStyle, ExpandExcerpts, GutterDimensions, HalfPageDown,
+ HalfPageUp, HoveredCursor, LineDown, LineUp, OpenExcerpts, PageDown, PageUp, Point,
+ SelectPhase, Selection, SoftWrap, ToPoint, CURSORS_VISIBLE_FOR, MAX_LINE_LEN,
};
use anyhow::Result;
use collections::{BTreeMap, HashMap};
@@ -257,6 +257,9 @@ impl EditorElement {
register_action(view, cx, Editor::move_to_enclosing_bracket);
register_action(view, cx, Editor::undo_selection);
register_action(view, cx, Editor::redo_selection);
+ if !view.read(cx).is_singleton(cx) {
+ register_action(view, cx, Editor::expand_excerpts);
+ }
register_action(view, cx, Editor::go_to_diagnostic);
register_action(view, cx, Editor::go_to_prev_diagnostic);
register_action(view, cx, Editor::go_to_hunk);
@@ -1543,6 +1546,7 @@ impl EditorElement {
range,
starts_new_buffer,
height,
+ id,
..
} => {
let include_root = self
@@ -1700,45 +1704,38 @@ impl EditorElement {
)
.h_full()
.child(
- ButtonLike::new("jump-icon")
+ ButtonLike::new("expand-icon")
.style(ButtonStyle::Transparent)
.child(
svg()
- .path(IconName::ArrowUpRight.path())
+ .path(IconName::ExpandVertical.path())
.size(IconSize::XSmall.rems())
- .text_color(cx.theme().colors().border)
- .group_hover("excerpt-jump-action", |style| {
+ .text_color(
+ cx.theme().colors().editor_line_number,
+ )
+ .group("")
+ .hover(|style| {
style.text_color(
- cx.theme().colors().editor_line_number,
+ cx.theme()
+ .colors()
+ .editor_active_line_number,
)
}),
)
- .when_some(jump_data.clone(), |this, jump_data| {
- this.on_click(cx.listener_for(&self.editor, {
- let path = jump_data.path.clone();
- move |editor, _, cx| {
- editor.jump(
- path.clone(),
- jump_data.position,
- jump_data.anchor,
- jump_data.line_offset_from_top,
- cx,
- );
- }
- }))
- .tooltip({
- move |cx| {
- Tooltip::for_action(
- format!(
- "Jump to {}:L{}",
- jump_data.path.path.display(),
- jump_data.position.row + 1
- ),
- &OpenExcerpts,
- cx,
- )
- }
- })
+ .on_click(cx.listener_for(&self.editor, {
+ let id = *id;
+ move |editor, _, cx| {
+ editor.expand_excerpt(id, cx);
+ }
+ }))
+ .tooltip({
+ move |cx| {
+ Tooltip::for_action(
+ "Expand Excerpt",
+ &ExpandExcerpts { lines: 0 },
+ cx,
+ )
+ }
}),
),
)
diff --git a/crates/multi_buffer/Cargo.toml b/crates/multi_buffer/Cargo.toml
index f866217da8635edee8433ad2e4fa46a0c561b8bd..611cec57e00012fa4688c80c39d677d3ad7555d0 100644
--- a/crates/multi_buffer/Cargo.toml
+++ b/crates/multi_buffer/Cargo.toml
@@ -24,14 +24,18 @@ test-support = [
anyhow.workspace = true
clock.workspace = true
collections.workspace = true
+ctor.workspace = true
+env_logger.workspace = true
futures.workspace = true
git.workspace = true
gpui.workspace = true
+itertools.workspace = true
language.workspace = true
log.workspace = true
parking_lot.workspace = true
rand.workspace = true
settings.workspace = true
+smallvec.workspace = true
sum_tree.workspace = true
text.workspace = true
theme.workspace = true
diff --git a/crates/multi_buffer/src/multi_buffer.rs b/crates/multi_buffer/src/multi_buffer.rs
index 365f8d1e1b7a988f7d573295cb9fcf49c753e619..ee2d00aa043bf39aa7a9176d6748822e9ca80dbb 100644
--- a/crates/multi_buffer/src/multi_buffer.rs
+++ b/crates/multi_buffer/src/multi_buffer.rs
@@ -7,6 +7,7 @@ use collections::{BTreeMap, Bound, HashMap, HashSet};
use futures::{channel::mpsc, SinkExt};
use git::diff::DiffHunk;
use gpui::{AppContext, EventEmitter, Model, ModelContext};
+use itertools::Itertools;
use language::{
char_kind,
language_settings::{language_settings, LanguageSettings},
@@ -15,6 +16,7 @@ use language::{
Outline, OutlineItem, Point, PointUtf16, Selection, TextDimension, ToOffset as _,
ToOffsetUtf16 as _, ToPoint as _, ToPointUtf16 as _, TransactionId, Unclipped,
};
+use smallvec::SmallVec;
use std::{
borrow::Cow,
cell::{Ref, RefCell},
@@ -1008,12 +1010,12 @@ impl MultiBuffer {
anchor_ranges.extend(ranges.by_ref().take(range_count).map(|range| {
let start = Anchor {
buffer_id: Some(buffer_id),
- excerpt_id: excerpt_id,
+ excerpt_id,
text_anchor: buffer_snapshot.anchor_after(range.start),
};
let end = Anchor {
buffer_id: Some(buffer_id),
- excerpt_id: excerpt_id,
+ excerpt_id,
text_anchor: buffer_snapshot.anchor_after(range.end),
};
start..end
@@ -1573,6 +1575,86 @@ impl MultiBuffer {
self.as_singleton().unwrap().read(cx).is_parsing()
}
+ pub fn expand_excerpts(
+ &mut self,
+ ids: impl IntoIterator- ,
+ line_count: u32,
+ cx: &mut ModelContext,
+ ) {
+ if line_count == 0 {
+ return;
+ }
+ self.sync(cx);
+
+ let snapshot = self.snapshot(cx);
+ let locators = snapshot.excerpt_locators_for_ids(ids);
+ let mut new_excerpts = SumTree::new();
+ let mut cursor = snapshot.excerpts.cursor::<(Option<&Locator>, usize)>();
+ let mut edits = Vec::>::new();
+
+ for locator in &locators {
+ let prefix = cursor.slice(&Some(locator), Bias::Left, &());
+ new_excerpts.append(prefix, &());
+
+ let mut excerpt = cursor.item().unwrap().clone();
+ let old_text_len = excerpt.text_summary.len;
+
+ let start_row = excerpt
+ .range
+ .context
+ .start
+ .to_point(&excerpt.buffer)
+ .row
+ .saturating_sub(line_count);
+ let start_point = Point::new(start_row, 0);
+ excerpt.range.context.start = excerpt.buffer.anchor_before(start_point);
+
+ let end_point = excerpt.buffer.clip_point(
+ excerpt.range.context.end.to_point(&excerpt.buffer) + Point::new(line_count, 0),
+ Bias::Left,
+ );
+ excerpt.range.context.end = excerpt.buffer.anchor_after(end_point);
+ excerpt.max_buffer_row = end_point.row;
+
+ excerpt.text_summary = excerpt
+ .buffer
+ .text_summary_for_range(start_point..end_point);
+
+ let new_start_offset = new_excerpts.summary().text.len;
+ let old_start_offset = cursor.start().1;
+ let edit = Edit {
+ old: old_start_offset..old_start_offset + old_text_len,
+ new: new_start_offset..new_start_offset + excerpt.text_summary.len,
+ };
+
+ if let Some(last_edit) = edits.last_mut() {
+ if last_edit.old.end == edit.old.start {
+ last_edit.old.end = edit.old.end;
+ last_edit.new.end = edit.new.end;
+ } else {
+ edits.push(edit);
+ }
+ } else {
+ edits.push(edit);
+ }
+
+ new_excerpts.push(excerpt, &());
+
+ cursor.next(&());
+ }
+
+ new_excerpts.append(cursor.suffix(&()), &());
+
+ drop(cursor);
+ self.snapshot.borrow_mut().excerpts = new_excerpts;
+
+ self.subscriptions.publish_mut(edits);
+ cx.emit(Event::Edited {
+ singleton_buffer_edited: false,
+ });
+ cx.notify();
+ }
+
fn sync(&self, cx: &AppContext) {
let mut snapshot = self.snapshot.borrow_mut();
let mut excerpts_to_edit = Vec::new();
@@ -1796,6 +1878,19 @@ impl MultiBuffer {
log::info!("Clearing multi-buffer");
self.clear(cx);
continue;
+ } else if rng.gen_bool(0.1) && !self.excerpt_ids().is_empty() {
+ let ids = self.excerpt_ids();
+ let mut excerpts = HashSet::default();
+ for _ in 0..rng.gen_range(0..ids.len()) {
+ excerpts.extend(ids.choose(rng).copied());
+ }
+
+ let line_count = rng.gen_range(0..5);
+
+ log::info!("Expanding excerpts {excerpts:?} by {line_count} lines");
+
+ self.expand_excerpts(excerpts.iter().cloned(), line_count, cx);
+ continue;
}
let excerpt_ids = self.excerpt_ids();
@@ -3361,6 +3456,39 @@ impl MultiBufferSnapshot {
}
}
+ // Returns the locators referenced by the given excerpt ids, sorted by locator.
+ fn excerpt_locators_for_ids(
+ &self,
+ ids: impl IntoIterator
- ,
+ ) -> SmallVec<[Locator; 1]> {
+ let mut sorted_ids = ids.into_iter().collect::>();
+ sorted_ids.sort_unstable();
+ let mut locators = SmallVec::new();
+
+ while sorted_ids.last() == Some(&ExcerptId::max()) {
+ sorted_ids.pop();
+ locators.push(Locator::max());
+ }
+
+ let mut sorted_ids = sorted_ids.into_iter().dedup().peekable();
+ if sorted_ids.peek() == Some(&ExcerptId::min()) {
+ sorted_ids.next();
+ locators.push(Locator::min());
+ }
+
+ let mut cursor = self.excerpt_ids.cursor::();
+ for id in sorted_ids {
+ if cursor.seek_forward(&id, Bias::Left, &()) {
+ locators.push(cursor.item().unwrap().locator.clone());
+ } else {
+ panic!("invalid excerpt id {:?}", id);
+ }
+ }
+
+ locators.sort_unstable();
+ locators
+ }
+
pub fn buffer_id_for_excerpt(&self, excerpt_id: ExcerptId) -> Option {
Some(self.excerpt(excerpt_id)?.buffer_id)
}
@@ -4286,7 +4414,8 @@ where
.peekable();
while let Some(range) = range_iter.next() {
let excerpt_start = Point::new(range.start.row.saturating_sub(context_line_count), 0);
- let mut excerpt_end = Point::new(range.end.row + context_line_count, 0).min(max_point);
+ // These + 1s ensure that we select the whole next line
+ let mut excerpt_end = Point::new(range.end.row + 1 + context_line_count, 0).min(max_point);
let mut ranges_in_excerpt = 1;
@@ -4323,6 +4452,13 @@ mod tests {
use std::env;
use util::test::sample_text;
+ #[ctor::ctor]
+ fn init_logger() {
+ if std::env::var("RUST_LOG").is_ok() {
+ env_logger::init();
+ }
+ }
+
#[gpui::test]
fn test_singleton(cx: &mut AppContext) {
let buffer = cx.new_model(|cx| Buffer::local(sample_text(6, 6, 'a'), cx));
@@ -4721,6 +4857,59 @@ mod tests {
assert_eq!(*follower_edit_event_count.read(), 4);
}
+ #[gpui::test]
+ fn test_expand_excerpts(cx: &mut AppContext) {
+ let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
+ let multibuffer = cx.new_model(|_| MultiBuffer::new(0, Capability::ReadWrite));
+
+ multibuffer.update(cx, |multibuffer, cx| {
+ multibuffer.push_excerpts_with_context_lines(
+ buffer.clone(),
+ vec![
+ // Note that in this test, this first excerpt
+ // does not contain a new line
+ Point::new(3, 2)..Point::new(3, 3),
+ Point::new(7, 1)..Point::new(7, 3),
+ Point::new(15, 0)..Point::new(15, 0),
+ ],
+ 1,
+ cx,
+ )
+ });
+
+ multibuffer.update(cx, |multibuffer, cx| {
+ multibuffer.expand_excerpts(multibuffer.excerpt_ids(), 1, cx)
+ });
+
+ let snapshot = multibuffer.read(cx).snapshot(cx);
+
+ // Expanding context lines causes the line containing 'fff' to appear in two different excerpts.
+ // We don't attempt to merge them, because removing the excerpt could create inconsistency with other layers
+ // that are tracking excerpt ids.
+ assert_eq!(
+ snapshot.text(),
+ concat!(
+ "bbb\n", // Preserve newlines
+ "ccc\n", //
+ "ddd\n", //
+ "eee\n", //
+ "fff\n", // <- Same as below
+ "\n", // Excerpt boundary
+ "fff\n", // <- Same as above
+ "ggg\n", //
+ "hhh\n", //
+ "iii\n", //
+ "jjj\n", //
+ "\n", //
+ "nnn\n", //
+ "ooo\n", //
+ "ppp\n", //
+ "qqq\n", //
+ "rrr\n", //
+ )
+ );
+ }
+
#[gpui::test]
fn test_push_excerpts_with_context_lines(cx: &mut AppContext) {
let buffer = cx.new_model(|cx| Buffer::local(sample_text(20, 3, 'a'), cx));
@@ -4729,6 +4918,8 @@ mod tests {
multibuffer.push_excerpts_with_context_lines(
buffer.clone(),
vec![
+ // Note that in this test, this first excerpt
+ // does contain a new line
Point::new(3, 2)..Point::new(4, 2),
Point::new(7, 1)..Point::new(7, 3),
Point::new(15, 0)..Point::new(15, 0),
@@ -4741,7 +4932,23 @@ mod tests {
let snapshot = multibuffer.read(cx).snapshot(cx);
assert_eq!(
snapshot.text(),
- "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\n"
+ concat!(
+ "bbb\n", // Preserve newlines
+ "ccc\n", //
+ "ddd\n", //
+ "eee\n", //
+ "fff\n", //
+ "ggg\n", //
+ "hhh\n", //
+ "iii\n", //
+ "jjj\n", //
+ "\n", //
+ "nnn\n", //
+ "ooo\n", //
+ "ppp\n", //
+ "qqq\n", //
+ "rrr\n", //
+ )
);
assert_eq!(
@@ -4777,7 +4984,23 @@ mod tests {
let snapshot = multibuffer.update(cx, |multibuffer, cx| multibuffer.snapshot(cx));
assert_eq!(
snapshot.text(),
- "bbb\nccc\nddd\neee\nfff\nggg\nhhh\niii\njjj\n\nnnn\nooo\nppp\nqqq\n"
+ concat!(
+ "bbb\n", //
+ "ccc\n", //
+ "ddd\n", //
+ "eee\n", //
+ "fff\n", //
+ "ggg\n", //
+ "hhh\n", //
+ "iii\n", //
+ "jjj\n", //
+ "\n", //
+ "nnn\n", //
+ "ooo\n", //
+ "ppp\n", //
+ "qqq\n", //
+ "rrr\n", //
+ )
);
assert_eq!(
@@ -5027,10 +5250,45 @@ mod tests {
for _ in 0..operations {
match rng.gen_range(0..100) {
- 0..=19 if !buffers.is_empty() => {
+ 0..=14 if !buffers.is_empty() => {
let buffer = buffers.choose(&mut rng).unwrap();
buffer.update(cx, |buf, cx| buf.randomly_edit(&mut rng, 5, cx));
}
+ 15..=19 if !expected_excerpts.is_empty() => {
+ multibuffer.update(cx, |multibuffer, cx| {
+ let ids = multibuffer.excerpt_ids();
+ let mut excerpts = HashSet::default();
+ for _ in 0..rng.gen_range(0..ids.len()) {
+ excerpts.extend(ids.choose(&mut rng).copied());
+ }
+
+ let line_count = rng.gen_range(0..5);
+
+ let excerpt_ixs = excerpts
+ .iter()
+ .map(|id| excerpt_ids.iter().position(|i| i == id).unwrap())
+ .collect::>();
+ log::info!("Expanding excerpts {excerpt_ixs:?} by {line_count} lines");
+ multibuffer.expand_excerpts(excerpts.iter().cloned(), line_count, cx);
+
+ if line_count > 0 {
+ for id in excerpts {
+ let excerpt_ix = excerpt_ids.iter().position(|&i| i == id).unwrap();
+ let (buffer, range) = &mut expected_excerpts[excerpt_ix];
+ let snapshot = buffer.read(cx).snapshot();
+ let mut point_range = range.to_point(&snapshot);
+ point_range.start =
+ Point::new(point_range.start.row.saturating_sub(line_count), 0);
+ point_range.end = snapshot.clip_point(
+ Point::new(point_range.end.row + line_count, 0),
+ Bias::Left,
+ );
+ *range = snapshot.anchor_before(point_range.start)
+ ..snapshot.anchor_after(point_range.end);
+ }
+ }
+ });
+ }
20..=29 if !expected_excerpts.is_empty() => {
let mut ids_to_remove = vec![];
for _ in 0..rng.gen_range(1..=3) {
@@ -5093,8 +5351,9 @@ mod tests {
_ => {
let buffer_handle = if buffers.is_empty() || rng.gen_bool(0.4) {
let base_text = util::RandomCharIter::new(&mut rng)
- .take(10)
+ .take(25)
.collect::();
+
buffers.push(cx.new_model(|cx| Buffer::local(base_text, cx)));
buffers.last().unwrap()
} else {
diff --git a/crates/sum_tree/src/cursor.rs b/crates/sum_tree/src/cursor.rs
index 12ab12dc27b9a2611983806665aa840e0ac32caa..4604d9e9fff000faf69a16d97233ddfbaef60bc0 100644
--- a/crates/sum_tree/src/cursor.rs
+++ b/crates/sum_tree/src/cursor.rs
@@ -405,6 +405,7 @@ where
summary.0
}
+ /// Returns whether we found the item you where seeking for
fn seek_internal(
&mut self,
target: &dyn SeekTarget<'a, T::Summary, D>,
diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs
index 1bf4505032578431f5b26684243d46c04c930ab8..f31db36204e02080ed52646062ed972b667a7143 100644
--- a/crates/ui/src/components/icon.rs
+++ b/crates/ui/src/components/icon.rs
@@ -47,6 +47,7 @@ pub enum IconName {
ChevronLeft,
ChevronRight,
ChevronUp,
+ ExpandVertical,
Close,
Collab,
Command,
@@ -149,6 +150,7 @@ impl IconName {
IconName::ChevronLeft => "icons/chevron_left.svg",
IconName::ChevronRight => "icons/chevron_right.svg",
IconName::ChevronUp => "icons/chevron_up.svg",
+ IconName::ExpandVertical => "icons/expand_vertical.svg",
IconName::Close => "icons/x.svg",
IconName::Collab => "icons/user_group_16.svg",
IconName::Command => "icons/command.svg",
diff --git a/crates/workspace/src/persistence.rs b/crates/workspace/src/persistence.rs
index 322945c9c0c4984c41b2c705004b0d8947d399c2..3c4efa7669b98e7de9ca3b142a39b31e6ca90f83 100644
--- a/crates/workspace/src/persistence.rs
+++ b/crates/workspace/src/persistence.rs
@@ -289,7 +289,6 @@ define_connection! {
sql!(
ALTER TABLE workspaces ADD COLUMN centered_layout INTEGER; //bool
),
-
];
}
diff --git a/script/generate-licenses b/script/generate-licenses
index 79dd88451426b509ec4dd05259a02d2dd29c2e7e..d2c3aa3bcfe96514fd1d2458587edff60ce8955c 100755
--- a/script/generate-licenses
+++ b/script/generate-licenses
@@ -7,10 +7,11 @@ OUTPUT_FILE="${1:-$(pwd)/assets/licenses.md}"
> $OUTPUT_FILE
echo -e "# ###### THEME LICENSES ######\n" >> $OUTPUT_FILE
-
-echo "Generating theme licenses"
cat assets/themes/LICENSES >> $OUTPUT_FILE
+echo -e "# ###### ICON LICENSES ######\n" >> $OUTPUT_FILE
+cat assets/icons/LICENSES >> $OUTPUT_FILE
+
echo -e "# ###### CODE LICENSES ######\n" >> $OUTPUT_FILE
[[ "$(cargo about --version)" == "cargo-about 0.6.1" ]] || cargo install cargo-about@0.6.1