Skip to content

Commit

Permalink
Highlight git/VCS modified files in explorer, palette, and buffer tabs (
Browse files Browse the repository at this point in the history
#1856)

* refactor(data/source control): Use IndexMap for VCS diffs

Using a map of path -> diff makes it easier and faster to, for example,
color explorer entries and tab labels according to their VCS status.

* feat(explorer): Color files and folders according to VCS status

* feat(tab headers): Color editor tabs according to VCS status

* feat(palette): Highlight files in palette according to VCS status
  • Loading branch information
claytonrcarter committed Jan 4, 2023
1 parent a9bee50 commit 9d0a33f
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 67 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

- [#1835](https://github.com/lapce/lapce/pull/1835): Add mouse keybinds

- [#1856](https://github.com/lapce/lapce/pull/1856): Highlight git/VCS modified files in explorer, palette, and buffer tabs

### Bug Fixes
- [#1911](https://github.com/lapce/lapce/pull/1911): Fix movement on selections with left/right arrow keys

Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

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

6 changes: 4 additions & 2 deletions lapce-data/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1243,6 +1243,7 @@ impl LapceTabData {
db: self.db.clone(),
focus_area: self.focus_area.clone(),
terminal: self.terminal.clone(),
source_control: self.source_control.clone(),
}
}

Expand Down Expand Up @@ -1658,14 +1659,15 @@ impl LapceTabData {
.file_diffs
.iter()
.filter_map(
|(diff, checked)| {
|(_, (diff, checked))| {
if *checked {
Some(diff.clone())
Some(diff)
} else {
None
}
},
)
.cloned()
.collect();
if diffs.is_empty() {
return;
Expand Down
3 changes: 1 addition & 2 deletions lapce-data/src/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -997,8 +997,7 @@ impl LapceEditorBufferData {
.source_control
.file_diffs
.iter()
.map(|(diff, _)| {
let path = diff.path();
.map(|(path, _)| {
let mut positions = Vec::new();
if let Some(doc) = self.main_split.open_docs.get(path) {
if let Some(history) = doc.get_history("head") {
Expand Down
15 changes: 11 additions & 4 deletions lapce-data/src/palette.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use lapce_core::{
language::LapceLanguage,
mode::Mode,
};
use lapce_rpc::proxy::ProxyResponse;
use lapce_rpc::{proxy::ProxyResponse, source_control::FileDiff};
use lsp_types::{DocumentSymbolResponse, Position, Range, SymbolKind};
use uuid::Uuid;

Expand All @@ -44,6 +44,7 @@ use crate::{
list::ListData,
panel::PanelKind,
proxy::{path_from_url, LapceProxy},
source_control::SourceControlData,
terminal::TerminalPanelData,
};

Expand Down Expand Up @@ -135,7 +136,7 @@ pub enum PaletteStatus {

#[derive(Clone, Debug, PartialEq)]
pub enum PaletteItemContent {
File(PathBuf, PathBuf),
File(PathBuf, PathBuf, Option<FileDiff>),
Line(usize, String),
TerminalLine(i32, String),
DocumentSymbol {
Expand Down Expand Up @@ -168,7 +169,7 @@ impl PaletteItemContent {
preview_editor_id: WidgetId,
) -> bool {
match &self {
PaletteItemContent::File(_, full_path) => {
PaletteItemContent::File(_, full_path, _) => {
if !preview {
ctx.submit_command(Command::new(
LAPCE_UI_COMMAND,
Expand Down Expand Up @@ -324,6 +325,7 @@ pub struct PaletteViewData {
pub db: Arc<LapceDb>,
pub focus_area: FocusArea,
pub terminal: Arc<TerminalPanelData>,
pub source_control: Arc<SourceControlData>,
}

impl Lens<LapceTabData, PaletteViewData> for PaletteViewLens {
Expand Down Expand Up @@ -839,6 +841,7 @@ impl PaletteViewData {
let widget_id = self.palette.widget_id;
let workspace = self.workspace.clone();
let event_sink = ctx.get_external_handle();
let file_diffs = self.source_control.file_diffs.clone();
self.palette.proxy.proxy_rpc.get_files(move |result| {
if let Ok(ProxyResponse::GetFilesResponse { items }) = result {
let items: im::Vector<PaletteItem> = items
Expand All @@ -853,9 +856,13 @@ impl PaletteViewData {
.unwrap_or(&full_path)
.to_path_buf();
}
let file_diff =
file_diffs.get(&full_path).cloned().map(|t| t.0);
let filter_text = path.to_str().unwrap_or("").to_string();
PaletteItem {
content: PaletteItemContent::File(path, full_path),
content: PaletteItemContent::File(
path, full_path, file_diff,
),
filter_text,
score: 0,
indices: Vec::new(),
Expand Down
13 changes: 9 additions & 4 deletions lapce-data/src/source_control.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::path::PathBuf;

use druid::{Command, Env, EventCtx, Modifiers, Target, WidgetId};
use indexmap::IndexMap;
use lapce_core::{
command::{FocusCommand, MoveCommand},
mode::Mode,
Expand All @@ -25,7 +28,8 @@ pub struct SourceControlData {
pub file_list_index: usize,
pub editor_view_id: WidgetId,
pub commit_button_id: WidgetId,
pub file_diffs: Vec<(FileDiff, bool)>,
// VCS modified files & whether they should be included in the next commit
pub file_diffs: IndexMap<PathBuf, (FileDiff, bool)>,
pub branch: String,
pub branches: im::Vector<String>,
}
Expand All @@ -43,7 +47,7 @@ impl SourceControlData {
commit_button_id: WidgetId::next(),
split_id: WidgetId::next(),
split_direction: SplitDirection::Horizontal,
file_diffs: Vec::new(),
file_diffs: IndexMap::new(),
branch: "".to_string(),
branches: im::Vector::new(),
}
Expand Down Expand Up @@ -183,9 +187,10 @@ impl KeyPressFocus for SourceControlData {
ctx.submit_command(Command::new(
LAPCE_UI_COMMAND,
LapceUICommand::OpenFileDiff(
self.file_diffs[self.file_list_index]
self.file_diffs
.get_index(self.file_list_index)
.unwrap()
.0
.path()
.clone(),
"head".to_string(),
),
Expand Down
16 changes: 8 additions & 8 deletions lapce-proxy/src/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1120,24 +1120,24 @@ fn git_diff_new(workspace_path: &Path) -> Option<DiffInfo> {
let mut renames = Vec::new();
let mut renamed_deltas = HashSet::new();

for (i, delta) in deltas.iter().enumerate() {
for (added_index, delta) in deltas.iter().enumerate() {
if delta.0 == git2::Delta::Added {
for (j, d) in deltas.iter().enumerate() {
for (deleted_index, d) in deltas.iter().enumerate() {
if d.0 == git2::Delta::Deleted && d.1 == delta.1 {
renames.push((i, j));
renamed_deltas.insert(i);
renamed_deltas.insert(j);
renames.push((added_index, deleted_index));
renamed_deltas.insert(added_index);
renamed_deltas.insert(deleted_index);
break;
}
}
}
}

let mut file_diffs = Vec::new();
for (i, j) in renames.iter() {
for (added_index, deleted_index) in renames.iter() {
file_diffs.push(FileDiff::Renamed(
deltas[*i].2.clone(),
deltas[*j].2.clone(),
deltas[*added_index].2.clone(),
deltas[*deleted_index].2.clone(),
));
}
for (i, delta) in deltas.iter().enumerate() {
Expand Down
1 change: 1 addition & 0 deletions lapce-ui/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ lsp-types = { version = "0.93", features = ["proposed"] }
toml_edit = { version = "0.14.4", features = ["easy"] }
open = "3.0.2"
hashbrown = { version = "0.13.1", features = ["serde"] }
indexmap = "1.7.0"

# lapce deps
druid = { git = "https://github.com/lapce/druid", branch = "shell_opengl", features = ["svg", "im", "serde"] }
Expand Down
39 changes: 25 additions & 14 deletions lapce-ui/src/editor/tab_header_content.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use lapce_data::{
document::BufferContent,
editor::TabRect,
};
use lapce_rpc::source_control::FileDiff;

use crate::editor::tab::TabRectRenderer;

Expand Down Expand Up @@ -463,12 +464,21 @@ impl Widget<LapceTabData> for LapceEditorTabHeaderContent {
data.config
.get_color_unchecked(LapceTheme::LAPCE_ICON_ACTIVE),
);
let mut text_color = match editor_tab.active_child() {
Some(active_child)
if active_child.widget_id() == child.widget_id() =>
{
LapceTheme::LAPCE_TAB_ACTIVE_FOREGROUND
}
_ => LapceTheme::LAPCE_TAB_INACTIVE_FOREGROUND,
};
let mut file_path = None;
match child {
EditorTabChild::Editor(view_id, _, _) => {
let editor = data.main_split.editors.get(view_id).unwrap();
if let BufferContent::File(path) = &editor.content {
(svg, svg_color) = data.config.file_svg(path);

if let Some(file_name) = path.file_name() {
if let Some(s) = file_name.to_str() {
text = s.to_string();
Expand All @@ -480,6 +490,20 @@ impl Widget<LapceTabData> for LapceEditorTabHeaderContent {
}
}
}
if let Some(diff) = data.source_control.file_diffs.get(path)
{
text_color = match diff.0 {
FileDiff::Modified(_) | FileDiff::Renamed(_, _) => {
LapceTheme::SOURCE_CONTROL_MODIFIED
}
FileDiff::Added(_) => {
LapceTheme::SOURCE_CONTROL_ADDED
}
FileDiff::Deleted(_) => {
LapceTheme::SOURCE_CONTROL_REMOVED
}
};
}
} else if let BufferContent::Scratch(..) = &editor.content {
text = editor.content.file_name().to_string();
}
Expand All @@ -498,20 +522,7 @@ impl Widget<LapceTabData> for LapceEditorTabHeaderContent {
.text()
.new_text_layout(text)
.font(data.config.ui.font_family(), font_size)
.text_color(
data.config
.get_color_unchecked(
if editor_tab.active_child().is_some()
&& editor_tab.active_child().unwrap().widget_id()
== child.widget_id()
{
LapceTheme::LAPCE_TAB_ACTIVE_FOREGROUND
} else {
LapceTheme::LAPCE_TAB_INACTIVE_FOREGROUND
},
)
.clone(),
)
.text_color(data.config.get_color_unchecked(text_color).clone())
.build()
.unwrap();
let path_layout = file_path.map(|f| {
Expand Down
43 changes: 37 additions & 6 deletions lapce-ui/src/explorer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use lapce_data::{
panel::PanelKind,
proxy::LapceProxy,
};
use lapce_rpc::file::FileNodeItem;
use lapce_rpc::{file::FileNodeItem, source_control::FileDiff};

use crate::{
editor::view::LapceEditorView,
Expand All @@ -41,6 +41,7 @@ fn paint_single_file_node_item(
hovered: Option<usize>,
config: &LapceConfig,
toggle_rects: &mut HashMap<usize, Rect>,
file_diff: Option<FileDiff>,
) {
let background = if Some(item.path_buf.as_ref()) == active {
Some(LapceTheme::PANEL_CURRENT_BACKGROUND)
Expand All @@ -62,6 +63,18 @@ fn paint_single_file_node_item(
);
}

let text_color = if let Some(diff) = file_diff {
match diff {
FileDiff::Modified(_) | FileDiff::Renamed(_, _) => {
LapceTheme::SOURCE_CONTROL_MODIFIED
}
FileDiff::Added(_) => LapceTheme::SOURCE_CONTROL_ADDED,
FileDiff::Deleted(_) => LapceTheme::SOURCE_CONTROL_REMOVED,
}
} else {
LapceTheme::PANEL_FOREGROUND
};

let font_size = config.ui.font_size() as f64;

let y = current as f64 * line_height - line_height;
Expand Down Expand Up @@ -125,11 +138,7 @@ fn paint_single_file_node_item(
.to_string(),
)
.font(config.ui.font_family(), font_size)
.text_color(
config
.get_color_unchecked(LapceTheme::PANEL_FOREGROUND)
.clone(),
)
.text_color(config.get_color_unchecked(text_color).clone())
.build()
.unwrap();
ctx.draw_text(
Expand Down Expand Up @@ -194,6 +203,7 @@ pub fn paint_file_node_item(
hovered,
config,
toggle_rects,
get_item_diff(item, data),
);
}
}
Expand Down Expand Up @@ -272,6 +282,27 @@ pub fn get_item_children(
(i, None)
}

/// Get a FileDiff for the given FileNodeItem. If the given item is a folder
/// that contains changes, returns a "fake" FileDiff that can be used to style
/// the item accordingly.
fn get_item_diff<'data>(
item: &'data FileNodeItem,
data: &'data LapceTabData,
) -> Option<FileDiff> {
if item.is_dir {
data.source_control
.file_diffs
.keys()
.find(|path| path.as_path().starts_with(&item.path_buf))
.map(|path| FileDiff::Modified(path.clone()))
} else {
data.source_control
.file_diffs
.get(&item.path_buf)
.map(|d| d.0.clone())
}
}

pub fn get_item_children_mut(
i: usize,
index: usize,
Expand Down

0 comments on commit 9d0a33f

Please sign in to comment.