This breaks on multi-line selections, and only shows the author key instead of their name, but the data is there, and should be easy to polish once everything is in place to support it
37UOV7PCILKVEPDUBJHLHBZEOTQ5NX5FCV6MQWTRY5GM5KXZNDGAC
LQ3SUK3P3KXY5CQA552EJGFH2MESGNHKK4YZTIKOGFJAKVBMHHUQC
B7YKJDKD7ZQ2JV4FLKZUHMIH6BQXH57ALGQOGQ4YTFGITBYMWY4QC
BS2SCVKJS7HVJDGBLKPURU75NGJGH5YQ2KDAT6QNEYGUJBVS6FUQC
LSSPVZONPCHHLOWSJWORILOV6ZP55Q4DFIX47J7YG3VCHQCA6SBAC
S34LGQX3XOVZUKWNE2YQNB3LJPXBBHP5GUYPYGTBFV63HYBLTQWAC
7X2GGEHDEWGZCDFD2IAGUGHIPNFWY76TTVNKOIV7YL3D5PMAXX4AC
Ok(cx.string("Inline diff error"))
let hash = hash_found.expect(&format!("Couldn't find hash for given line {target_line}"));
let is_current_state = file_state.is_current_state(hash);
let change = if is_current_state {
file_state.current_state
} else {
file_state
.recorded_changes
.iter()
.find(|c| &c.hash().unwrap() == hash)
.unwrap()
.to_owned()
};
let change_object = cx.empty_object();
let change_line = cx.number(target_line as f64);
change_object.set(&mut cx, "line", change_line)?;
let change_hash = cx.string(change.hash().unwrap().to_base32());
change_object.set(&mut cx, "hash", change_hash)?;
if is_current_state {
let change_message = cx.string("Unrecorded changes");
change_object.set(&mut cx, "message", change_message)?;
let change_authors = cx.string("You");
change_object.set(&mut cx, "authors", change_authors)?;
let change_description = cx.string("TODO");
change_object.set(&mut cx, "description", change_description)?;
} else {
let change_message = cx.string(&change.header.message);
change_object.set(&mut cx, "message", change_message)?;
let change_description =
cx.string(change.header.description.to_owned().unwrap_or_default());
change_object.set(&mut cx, "description", change_description)?;
let mut authors = Vec::new();
for author in &change.header.authors {
// TODO: associate this key to a specific author
let author_key = author.0.get("key").cloned().unwrap_or(String::new());
authors.push(author_key);
}
let change_authors = cx.string(authors.join(", "));
change_object.set(&mut cx, "authors", change_authors)?;
}
Ok(change_object)
import { commands, ExtensionContext, Uri, window, workspace, scm, SourceControl, RelativePattern, SourceControlResourceGroup, FileDecorationProvider, CancellationToken, Event, FileDecoration, ProviderResult, EventEmitter } from 'vscode';
import { commands, ExtensionContext, Uri, window, workspace, scm, SourceControl, RelativePattern, SourceControlResourceGroup, FileDecorationProvider, CancellationToken, Event, FileDecoration, ProviderResult, EventEmitter, DecorationRenderOptions, ThemeColor, Position, TextEditorDecorationType, Selection } from 'vscode';
let decorations: TextEditorDecorationType[] = [];
function credit(path: string, selections: readonly Selection[]) {
// TODO: cache everything (including decoration objects)
for (let decoration of decorations) {
decoration.dispose();
}
decorations = [];
const active_editor = window.activeTextEditor!;
let changes: ChangeObject[] = [];
for (let selection of selections) {
for (let line = selection.start.line; line <= selection.end.line; line++) {
const change_for_line = inlineCredit(path, line);
if (changes.length > 0) {
if (changes[-1].hash !== change_for_line.hash) {
changes.push(change_for_line);
}
} else {
changes.push(change_for_line);
}
}
}
for (let change of changes) {
const decoration_options: DecorationRenderOptions = {
after: {
// TODO: find a way to align this text
contentText: ` ${change.authors} | ${change.message}`,
color: new ThemeColor('disabledForeground'),
},
isWholeLine: true,
};
const decoration_type = window.createTextEditorDecorationType(decoration_options);
active_editor.setDecorations(decoration_type, active_editor.selections);
decorations.push(decoration_type);
}
}