Skip to content

Commit

Permalink
Add support for comments on nodes (enso-org/ide#1744)
Browse files Browse the repository at this point in the history
Original commit: enso-org/ide@fdeed13
  • Loading branch information
mwu-tow authored Aug 2, 2021
1 parent 118fcce commit f30fb17
Show file tree
Hide file tree
Showing 31 changed files with 1,113 additions and 370 deletions.
2 changes: 2 additions & 0 deletions ide/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ these updates be shipped in a stable release before the end of the year.

- [New look of open project dialog.][1700]. Now it has "Open project" title on
the top.
- [Documentation cooments are displayed next to the nodes.][1744].

#### Enso Compiler

Expand All @@ -31,6 +32,7 @@ these updates be shipped in a stable release before the end of the year.
[1700]: https://github.com/enso-org/ide/pull/1700
[1726]: https://github.com/enso-org/ide/pull/1726
[1743]: https://github.com/enso-org/ide/pull/1743
[1744]: https://github.com/enso-org/ide/pull/1744

# Enso 2.0.0-alpha.10 (2021-07-23)

Expand Down
23 changes: 15 additions & 8 deletions ide/src/rust/ensogl/lib/text/src/component/area.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ struct Lines {

impl Lines {
/// The number of visible lines.
pub fn count(&self) -> usize {
pub fn len(&self) -> usize {
self.rc.borrow().len()
}

Expand Down Expand Up @@ -260,6 +260,7 @@ ensogl_core::define_endpoints! {
Output {
pointer_style (cursor::Style),
width (f32),
height (f32),
changed (Vec<buffer::view::Change>),
content (Text),
hovered (bool),
Expand Down Expand Up @@ -600,7 +601,7 @@ impl AreaModel {
let id = sel.id;
let start_line = sel.start.line.as_usize();
let end_line = sel.end.line.as_usize();
let pos_x = |line:usize, column:Column| if line >= self.lines.count() {
let pos_x = |line:usize, column:Column| if line >= self.lines.len() {
self.lines.rc.borrow().last().and_then(|l| l.divs.last().cloned()).unwrap_or(0.0)
} else {
self.lines.rc.borrow()[line].div_by_column(column)
Expand Down Expand Up @@ -677,7 +678,7 @@ impl AreaModel {
fn get_in_text_location(&self, screen_pos:Vector2) -> Location {
let object_space = self.to_object_space(screen_pos);
let line_index = (-object_space.y / LINE_HEIGHT) as usize;
let line_index = std::cmp::min(line_index,self.lines.count() - 1);
let line_index = std::cmp::min(line_index,self.lines.len() - 1);
let div_index = self.lines.rc.borrow()[line_index].div_index_close_to(object_space.x);
let line = line_index.into();
let column = div_index.into();
Expand All @@ -690,19 +691,25 @@ impl AreaModel {
}

/// Redraw the text.
fn redraw(&self, width_may_change:bool) {
fn redraw(&self, size_may_change:bool) {
let lines = self.buffer.view_lines();
let line_count = lines.len();
self.lines.resize_with(line_count,|ix| self.new_line(ix));
let lengths = lines.into_iter().enumerate().map(|(view_line_index,content)|{
let widths = lines.into_iter().enumerate().map(|(view_line_index,content)|{
self.redraw_line(view_line_index,content)
}).collect_vec();
let length = lengths.into_iter().max_by(|x,y|x.partial_cmp(y).unwrap()).unwrap_or_default();
if width_may_change {
self.frp_endpoints.source.width.emit(length);
let width = widths.into_iter().max_by(|x, y|x.partial_cmp(y).unwrap()).unwrap_or_default();
if size_may_change {
let height = self.calculate_height();
self.frp_endpoints.source.width.emit(width);
self.frp_endpoints.source.height.emit(height);
}
}

fn calculate_height(&self) -> f32 {
self.lines.len() as f32 * LINE_HEIGHT
}

fn redraw_line(&self, view_line_index:usize, content:String) -> f32 {
let cursor_map = self.selection_map.borrow()
.location_map.get(&view_line_index).cloned().unwrap_or_default();
Expand Down
7 changes: 3 additions & 4 deletions ide/src/rust/ide/lib/ast/impl/src/crumbs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

use crate::prelude::*;

use crate::ShiftedVec1;
use crate::enumerate_non_empty_lines;
use crate::known;
use crate::Shifted;
use crate::MacroPatternMatch;
use crate::HasTokens;
use crate::Shape;
use crate::ShiftedVec1;
use crate::TokenConsumer;

use enso_data::text::Index;
Expand Down Expand Up @@ -1414,9 +1415,7 @@ where for<'t> &'t Shape<Ast> : TryInto<&'t T, Error=E>,
pub fn non_empty_line_indices<'a, T:'a>
(iter:impl Iterator<Item = &'a crate::BlockLine<Option<T>>> + 'a)
-> impl Iterator<Item=usize> + 'a {
iter.enumerate().filter_map(|(line_index,line)| {
line.elem.as_ref().map(|_| line_index)
})
enumerate_non_empty_lines(iter).map(|(index,_ast)| index)
}


Expand Down
82 changes: 67 additions & 15 deletions ide/src/rust/ide/lib/ast/impl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,6 @@ pub struct BlockLine <T> {
}



// =============
// === Macro ===
// =============
Expand Down Expand Up @@ -1201,29 +1200,82 @@ impl<T> BlockLine<T> {
pub fn new(elem:T) -> BlockLine<T> {
BlockLine {elem,off:0}
}

/// Convert `&BlockLine<T>` into `BlockLine<&T>`.
pub fn as_ref(&self) -> BlockLine<&T> {
BlockLine {
elem : &self.elem,
off : self.off,
}
}

/// Maps `BlockLine<T>` into `BlockLine<U>` using the provided function.
pub fn map<U>(self, f:impl FnOnce(T) -> U) -> BlockLine<U> {
BlockLine {
elem : f(self.elem),
off : self.off
}
}
}

impl <T> BlockLine<Option<T>> {
/// Transpose a `BlockLine<Option<T>>` into `Option<BlockLine<T>>`.
pub fn transpose(self) -> Option<BlockLine<T>> {
let off = self.off;
self.elem.map(|elem| BlockLine {elem,off})
}

/// Transpose a `&BlockLine<Option<T>>` into `Option<BlockLine<&T>>`.
pub fn transpose_ref(&self) -> Option<BlockLine<&T>> {
self.as_ref().map(Option::as_ref).transpose()
}

/// Map the inner contents of the line's stored element.
pub fn map_opt<U>(self, f:impl FnOnce(T) -> U) -> BlockLine<Option<U>> {
self.map(|elem| elem.map(f))
}
}

/// Iterate over non-empty lines, while maintaining their indices.
pub fn enumerate_non_empty_lines<'a,T:'a>(iter:impl IntoIterator<Item=&'a BlockLine<Option<T>>> + 'a)
-> impl Iterator<Item=(usize,BlockLine<&'a T>)> + 'a {
iter.into_iter().enumerate().filter_map(|(index,line):(usize,&BlockLine<Option<T>>)| {
let non_empty_line = line.transpose_ref()?;
Some((index, non_empty_line))
})
}

impl <T> Block<T> {
/// Concatenate `Block`'s `first_line` with `lines` and returns a collection with all the lines.
pub fn all_lines(&self) -> Vec<BlockLine<Option<T>>> where T:Clone {
let mut lines = Vec::new();
for off in &self.empty_lines {
/// Iterates over all lines in the block, including leading empty lines.
pub fn iter_all_lines(&self) -> impl Iterator<Item=BlockLine<Option<&T>>> + '_ {
let indent = self.indent;
let leading_empty_lines = self.empty_lines.iter().map(move |off| {
let elem = None;
// TODO [mwu]
// Empty lines use absolute indent, while BlockLines are relative to Block.
// We might lose some data here, as empty lines shorter than block will get filled
// with spaces. This is something that should be improved in the future but also
// requires changes in the AST.
let off = off.checked_sub(self.indent).unwrap_or(0);
lines.push(BlockLine{elem,off})
}
let off = off.saturating_sub(indent);
BlockLine {elem,off}
});

let first_line = std::iter::once(self.first_line.as_ref().map(Some));
let lines = self.lines.iter().map(|line| line.as_ref().map(|elem| elem.as_ref()));
leading_empty_lines.chain(first_line).chain(lines)
}

/// Calculate absolute indentation of lines in this block.
pub fn indent(&self, parent_indent:usize) -> usize {
parent_indent + self.indent
}

let first_line = self.first_line.clone();
let elem = Some(first_line.elem);
let off = first_line.off;
lines.push(BlockLine{elem,off});
lines.extend(self.lines.iter().cloned());
lines
/// Iterate over non-empty lines, while keeping their absolute indices.
pub fn enumerate_non_empty_lines(&self) -> impl Iterator<Item=(usize,BlockLine<&T>)> + '_ {
self.iter_all_lines().enumerate().filter_map(|(index,line):(usize,BlockLine<Option<&T>>)| {
let non_empty_line = line.transpose()?;
Some((index, non_empty_line))
})
}
}

Expand Down Expand Up @@ -1668,7 +1720,7 @@ mod tests {
let expected_repr = "\n \n head \n tail0 \n \n tail2 ";
assert_eq!(block.repr(), expected_repr);

let all_lines = block.all_lines();
let all_lines = block.iter_all_lines().collect_vec();
let (empty_line,head_line,tail0,tail1,tail2) = all_lines.iter().expect_tuple();
assert!(empty_line.elem.is_none());
assert_eq!(empty_line.off,1); // other 4 indents are provided by Block
Expand Down
Loading

0 comments on commit f30fb17

Please sign in to comment.