mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-13 04:34:21 -10:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de12bf1189 | ||
|
|
4c71891924 |
No files matched your search
@@ -4125,6 +4125,11 @@ impl PluginApi {
|
||||
if items.len() > 10_000 || file.as_ref().and_then(|f| f.badge.as_ref()).is_some_and(|b| b.chars().count() > 2) {
|
||||
return Err(HostError::Invalid("decoration limit exceeded".into()));
|
||||
}
|
||||
if let Some(note) = file.as_ref().and_then(|f| f.note.as_ref())
|
||||
&& (note.trim().is_empty() || note.chars().count() > 200 || note.contains(['\n', '\r']))
|
||||
{
|
||||
return Err(HostError::Invalid("a file note is one non-empty line of at most 200 characters".into()));
|
||||
}
|
||||
items.retain(|d| decoration_style(&d.style));
|
||||
if items.iter().any(|d| d.range.start > d.range.end) {
|
||||
return Err(HostError::Invalid("reversed decoration range".into()));
|
||||
@@ -4143,7 +4148,7 @@ impl PluginApi {
|
||||
set_id: set.into(),
|
||||
tree,
|
||||
items,
|
||||
file: file.filter(|f| decoration_style(&f.style)),
|
||||
file: file.filter(|f| f.note.is_some() || decoration_style(&f.style)),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
@@ -4315,10 +4320,33 @@ mod workbench_tests {
|
||||
api.file_decorations(
|
||||
Some(&path),
|
||||
"tree",
|
||||
Some(ide_plugin::FileDecoration { badge: Some("abc".into()), style: "info".into(), tooltip: None })
|
||||
Some(ide_plugin::FileDecoration {
|
||||
badge: Some("abc".into()),
|
||||
style: "info".into(),
|
||||
tooltip: None,
|
||||
note: None
|
||||
})
|
||||
)
|
||||
.is_err()
|
||||
);
|
||||
let note = |text: &str| ide_plugin::FileDecoration {
|
||||
badge: None,
|
||||
style: String::new(),
|
||||
tooltip: Some("why".into()),
|
||||
note: Some(text.into()),
|
||||
};
|
||||
api.file_decorations(Some(&path), "notes", Some(note("entry point"))).unwrap();
|
||||
let notes = |api: &PluginApi| {
|
||||
api.shared.decoration_sets()["test"]
|
||||
.iter()
|
||||
.filter(|s| s.tree && s.set_id == "notes")
|
||||
.map(|s| s.file.as_ref().and_then(|f| f.note.clone()))
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
assert_eq!(notes(&api), [Some("entry point".to_string())], "kept without a style");
|
||||
for bad in ["", "two\nlines", &"x".repeat(201)] {
|
||||
assert!(api.file_decorations(Some(&path), "notes", Some(note(bad))).is_err(), "{bad:?}");
|
||||
}
|
||||
api.shared.clear_plugin("test", true);
|
||||
assert!(api.shared.decoration_sets().is_empty());
|
||||
}
|
||||
|
||||
@@ -922,6 +922,9 @@ pub struct FileDecoration {
|
||||
pub badge: Option<String>,
|
||||
pub style: String,
|
||||
pub tooltip: Option<String>,
|
||||
/// Text shown after the name (API 1.7 `set-file-note`).
|
||||
#[serde(default)]
|
||||
pub note: Option<String>,
|
||||
}
|
||||
/// Commit metadata, date in Unix seconds.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Type)]
|
||||
|
||||
@@ -2497,7 +2497,7 @@ impl bindings::openidea::plugin::decorations::Host for StoreData {
|
||||
.file_decorations(
|
||||
Some(&real),
|
||||
&set_id,
|
||||
Some(crate::FileDecoration { badge: item.badge, style: item.style, tooltip: item.tooltip }),
|
||||
Some(crate::FileDecoration { badge: item.badge, style: item.style, tooltip: item.tooltip, note: None }),
|
||||
)
|
||||
.map_err(to_wit))
|
||||
}
|
||||
@@ -2507,6 +2507,17 @@ impl bindings::openidea::plugin::decorations::Host for StoreData {
|
||||
}
|
||||
Ok(self.host.file_decorations(None, &set_id, None).map_err(to_wit))
|
||||
}
|
||||
fn set_file_note(&mut self, path: String, set_id: String, note: String, tooltip: Option<String>) -> Fallible<()> {
|
||||
if let Err(e) = self.require(Capability::ProjectRead) {
|
||||
return Ok(Err(e));
|
||||
}
|
||||
let real = match self.decoration_path(&path) {
|
||||
Ok(real) => real,
|
||||
Err(e) => return Ok(Err(e)),
|
||||
};
|
||||
let item = crate::FileDecoration { badge: None, style: String::new(), tooltip, note: Some(note) };
|
||||
Ok(self.host.file_decorations(Some(&real), &set_id, Some(item)).map_err(to_wit))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod language_features_bindings {
|
||||
|
||||
@@ -1 +1 @@
|
||||
3c7f35facd15ee8380ccb6475b7c051d500e38346b711e1805077becd0c75f75
|
||||
d6c855f1f91aeb02eec5d6c8a07be4eb64bae0704619f44cb67f3b832daf01ee
|
||||
@@ -1 +1 @@
|
||||
3879822d975695c6258e95286b0e64c5ee1e3265876501efaf0e577b38f8222b
|
||||
51d00702c42c7167083caea70cf2df022e512bcaf89af8addf526421ff45a15f
|
||||
@@ -1 +1 @@
|
||||
228ae888bf556ce5cedc7843eb20e92f221d9e1f640f3c6c595bed3fd6be6051
|
||||
40d2fd76ba96b0c93ea0a034c6749709ddc00fc119046e653a50b180a9c4718d
|
||||
@@ -1 +1 @@
|
||||
41de239b6f723020b38eb2b67f642b7c88cc88c79117c3072ba122633afc418c
|
||||
08822287f3649412340f9dbbe2f0ea5a5cd2f543a3c242c5d0a29c422c4c5367
|
||||
@@ -1 +1 @@
|
||||
78c5ed3c756498c7619b46c3622ae7a59461c61c747b45caecd79b341ee654de
|
||||
43eba23cc14cf3c74bfc934099cd58df20f07ee5df96cc10100b90016c544a7a
|
||||
@@ -1 +1 @@
|
||||
ee848321e53cb181536e6158570dbb4ab02a6fd2a1a064b068803ac7da7f3448
|
||||
520d9a95328dc772bbb913a2e5e22af8243c95ca45744cbb65b25747653d2a34
|
||||
@@ -1 +1 @@
|
||||
b587de945875a98f1d4ca20fab7cf94fb4dc6d848136aa19ab0e0e5319155a80
|
||||
acd3d0ee3f886c6a271ce3139200ce5bdb46e40f9c68e495c5ff9b4db98a88ac
|
||||
@@ -1 +1 @@
|
||||
1c8776dcae35d2d49dd6c1e32b0cdd354de1eb0f72a473245a2c47368b89ec30
|
||||
0cf3bc2197f0bd5339fe3c2199bd973e68b3637b8c5ae07902e62659160275e3
|
||||
@@ -1 +1 @@
|
||||
2a517cbffd6d3cdda37117d8ca8815978a09995923fc3d5aa5af7020afdac56a
|
||||
17f837c8d6f58800728e00060afe68b2a093085d816d809c9e67065fdd165352
|
||||
@@ -1 +1 @@
|
||||
dbd912b1f8488ecd446af07b5dcaef55d44bce57c1a55be5c0b0fb33e2697903
|
||||
2cca80220fab6764a8e1f51db8ed2f55b603000c8d0dbf5913a441876b7857ba
|
||||
@@ -1 +1 @@
|
||||
efdc84cd2bedb3989b03d19b569d09958f26e502db65db4dd786eb3438a7c407
|
||||
54211437002ad83a9d3d642f2dca5f37cadd89d7d77ddc7de545db87b99fb8b7
|
||||
@@ -1 +1 @@
|
||||
be6bc15ee42a5e21781ba54f548007351a46b669882ee4491da20ff556927a06
|
||||
4326d9cdefe71f4bb9aab043ccef883abbd13145b1579352b97c66889f514c68
|
||||
@@ -1 +1 @@
|
||||
e5c3a3beda750dff27d7b823676d53f15b7c76b8ad539594cd913bd178d750da
|
||||
2469023f4f29b9abdaa27c9d96774229c4dd002366421dc508926c3fed1fba1b
|
||||
@@ -1 +1 @@
|
||||
322de3299f0413101c02358836e7df7e06e58cbb22c11897664564abbb8af090
|
||||
233461ab52a12e27fa600e108e83cab1b930b3e61812e0c048c99c1e18c6d646
|
||||
@@ -1 +1 @@
|
||||
d768ff6a4a466cc6f1d72499df3ccb4ae76872436b8eddff27f62aa156331a37
|
||||
bfc654523da608bbc008ea6a15a0cfd0b129ffab70088bf6b610786b63b5352e
|
||||
@@ -1 +1 @@
|
||||
57aea107b2c10e4d30fa3785ac4c6566f1b40908a18a3859aca8be047fac9518
|
||||
c8536be072d27aa89f5e92b5b96e38ed65b7f06c35c05ecbd4a151218203c5f7
|
||||
+1
-1
@@ -1 +1 @@
|
||||
c98bcc89750e26e738d7115a7c0454fde25367a0a23bdc2ff95fb5a5dacc9f98
|
||||
7c0c1f5035e12c794d48cb75a8fc259d11dd99ba3188030fe1d9956720ee6ad5
|
||||
@@ -1 +1 @@
|
||||
a4c23b93a14eda705cb18c88bbc2373d1ef3f96031ff2df21b8b092b50633996
|
||||
3cf5fd6ab0ce909b806230e20a7fa46264f85937018cfa68865ec0eeb92d4b72
|
||||
@@ -1 +1 @@
|
||||
aec002b3dd310068e69a6ae67a49d30655bf8baea9153a110a407e9d408e6880
|
||||
d349977fd3cbfba92d1d953ac09f65dae5b83b7070723b59553d791c638acf81
|
||||
@@ -1 +1 @@
|
||||
08ece563c3b55c2b86e68fbb0815ddcbb63beb6f1f6c32b8dbdbee558a4a66c1
|
||||
e796039ae2f8e534ffc8c2ed2e47e910aaf593c464525287699cf1daf3e195ef
|
||||
@@ -1 +1 @@
|
||||
450845edf234a1cc78cd6cfc0b812a89f3a2e41484689cc1e1b05be66873d4eb
|
||||
5e084fa409bb0641409110d91f203a6f99b451b95cd8067bd1ee68140bf8a892
|
||||
@@ -1 +1 @@
|
||||
61b735de5ef61dcd0ea8e640c2ad004e84a63fe4dfd7872ffb5e04d6d81dc9a9
|
||||
521557c1a062a9b82afa14547bc54b57255cdbed3b2ab4b1b86424dfb8accbdc
|
||||
@@ -1 +1 @@
|
||||
36776367782eaa4b8b8121f4a665dd8e68525a4836bff1c92bc16770cce14929
|
||||
5280990269e944aef81ec91b356fadf4aa2fc7e7bb10e4b6842e1dc1c669704a
|
||||
@@ -1 +1 @@
|
||||
f6311d232a99356b02a398b2ce3db0865c425f435a8d201157719178ba2b97c7
|
||||
ff1391d3c9338b6270fef8af7d7c4a5bc595c391997c220a3a827b4b8a068de8
|
||||
@@ -1 +1 @@
|
||||
fe1d26665e3c816ed43fc720acabad03a37b7924bccd4dd8c357fd156947b3c7
|
||||
b78ac0b6fa14401a6379f3e6d07d1398a63d70e882930b3747ec843c0fdb5de7
|
||||
@@ -1 +1 @@
|
||||
76bab8e48235f9f066f5b9bbfdd9398916b6c3ed73c072c543d80595130519f7
|
||||
55331477c1d5322b0dc35d13fc7f8223bf697f5f21328d340f75519dd1098727
|
||||
@@ -1 +1 @@
|
||||
f9ed2eac306229f76b05d0c4a4fb2f0ed8d81a1dfc5eb50d044bbe10c9206a5f
|
||||
0ae6b7edd0d7cd5025ead4a4afacf0fbe3ebc9548d847f94be0e63585a19747e
|
||||
@@ -1 +1 @@
|
||||
f2d83d9f56da072d38a1552195af8a9d4edc11888c645627d5dd1e4a46afc4df
|
||||
5d909d6ab2e73fabba2d213a944546ef7e425552852cf7f74e00eb94c9d167ac
|
||||
+5
-2
@@ -598,6 +598,7 @@ then run `openidea-plugin check`.
|
||||
| `TextEditor::set_selections(ranges)`, `reveal(range)` | `editor.text-editor` | API 1.4: selections or scrolling in this window's already open editor; no capability. Commands/events only, UTF-16 coordinates. |
|
||||
| `host::set_decorations`, `clear_decorations` | `decorations.{set,clear}` | API 1.4: project-scoped editor annotations cleared on plugin stop. Requires `project.read`. |
|
||||
| `host::set_file_decoration`, `clear_file_decorations` | `decorations.{set-file,clear-file}` | API 1.4: project-tree badges/styles. Requires `project.read`. |
|
||||
| `host::set_file_note` | `decorations.set-file-note` | API 1.7: a note after the name in the project tree (one line, at most 200 characters). Requires `project.read`. |
|
||||
| `Project::search_text(query, limit)` | `workspace.project.search-text` | API 1.4: cancellable Find in Files with unsaved documents and project excludes, at most 10,000 matches. Requires `project.read`. |
|
||||
| `host::problems(path)` | `diagnostics.problems` | API 1.4: project Problems reports grouped by file/source, optional file filter. Requires `project.read` and an invoking window. Empty for remote projects. |
|
||||
| `Project::vcs_log(path, limit)` | `vcs.log` | API 1.4: newest first, at most 1000 commits, optional file history. Requires `vcs.read` and trust. |
|
||||
@@ -851,8 +852,10 @@ Decorations are plain text, with fixed styles mapped to theme tokens:
|
||||
`highlight`, `search`, `added`, `modified`, `removed`, `warning`, `error`, `info`,
|
||||
`underline`, `strikethrough`, `muted`. Unknown styles are ignored. Editor items
|
||||
have `{ range, style, hover, after }`; tree items have `{ badge, style, tooltip }`,
|
||||
where a badge has at most two Unicode characters. Paths must resolve inside an
|
||||
open project; absolute paths select that project, relative paths use the invoking
|
||||
where a badge has at most two Unicode characters. A tree item can instead be a note
|
||||
(`set-file-note`, API 1.7): muted text after the file or folder name, one line of at
|
||||
most 200 characters, with an optional tooltip; it replaces that set's item for the file.
|
||||
Paths must resolve inside an open project; absolute paths select that project, relative paths use the invoking
|
||||
project. Sets are isolated by plugin and project and shared by all windows of
|
||||
that project. Setting replaces a set's items for one file; clearing removes that
|
||||
set in all projects. Each plugin has at most 50 editor sets and 50 tree sets,
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
e8e6dbe6dba09de2fd71a9d84eed8c01b16253f9247bf882361c6f49b8a4d51d
|
||||
b064bd91f44d088c778a0b7e207f9682a56156724588ff500c0c864d22085205
|
||||
@@ -1 +1 @@
|
||||
784a4e01725063fc2949a88bd209e7fcc8ecb0f721acd5f03d92db39ece091a9
|
||||
4145b677141c592dbd9130000eae707615ec36069b78ea3e25fe598dc642bf14
|
||||
+1
-1
@@ -1 +1 @@
|
||||
73670a049d8c108511af35b5030d08f1e04a9198cba0da54268e75a06747d953
|
||||
52f7ccad8966c991505e7a377c59dbf24d0660df66eca97e7a2a8c5d58e3ce68
|
||||
@@ -1 +1 @@
|
||||
a17332b7d5becc4ddccffdba1f9b009e07f75f171bc2519b6c1038fdda2bfd71
|
||||
a438e04a1e179469eec1ee16522b031fea9bbb669d34c77973ee6fd85885a088
|
||||
+1
-1
@@ -1 +1 @@
|
||||
3db5b81c6562e2532c9408d749cf65164247c0ef6d51e4195a44ebdc9a697924
|
||||
7ff4e304120c9c7bd316b95ce7526fda74adf00867642fcc66311effa1567d76
|
||||
+1
-1
@@ -1 +1 @@
|
||||
2c31b614b8c942fdfc075aa58da2000c85598f0c5031d565ffafeb60c75eeac5
|
||||
63847067fc7b9931a3d697d8e6649cea04a0af7ad02d57e26a38f9acb2e6fcdd
|
||||
+1
-1
@@ -1 +1 @@
|
||||
08ab43e65c6904d48a969cb0c4247ece1257b51600962fbc64e67d9a1a78e96a
|
||||
78b71cba21352bfc91cd631523e4b69a6a2df2d5f6bfbf8164e63698a4625594
|
||||
+1
-1
@@ -1 +1 @@
|
||||
c7aa8a41a0b142fac374470597316500e2f1b0dfb2c2e58c8e4bcbe05dd87c1f
|
||||
6d5ea800a0bcbf26e4770a985b1bc8ef09ca71e7e5c94d59f510dbd108c79ece
|
||||
@@ -1 +1 @@
|
||||
e8469311f7ccf2ed4ced5bfea4987cd3ff13aede56ee4b18652d3ab466316392
|
||||
21061c0875e8213efe809e95b0a4d4b0dd73962398fd793d176a443163e73e0e
|
||||
+1
-1
@@ -1 +1 @@
|
||||
79d714b6dcbd34cfe24f9b643c65e91c695d6ed3bd68d752a16c0b253ba27384
|
||||
6a95d38a5f41dbed72dca23584f715db9a12192d19222460cee8669b4a352770
|
||||
+1
-1
@@ -1 +1 @@
|
||||
e13b635a78df5d7de5bcc8bf2a75ab5699c6f06b97bd36cbfcfb110c9b332ff5
|
||||
bfab2d2fa19bdaac6890a117aa055c4caf1393065f87b6c104ff46114d9189c8
|
||||
+1
-1
@@ -1 +1 @@
|
||||
7debd0f77bdcd1eddaf84450f8070142e3622d1b826770826232f3211c008fc1
|
||||
1e860aa8277c6cc5ffd887e1bc5c3107feb8c7f856d2c4df7294497879308ce7
|
||||
+1
-1
@@ -1 +1 @@
|
||||
de2139c370c23f70bf2778b78967eea7617bc6c63f400bf7de5ad26a57f6da66
|
||||
cbe64480e49895004af403c165735d58cfe657910b45cea2d86d7eadcd93b93b
|
||||
+1
-1
@@ -1 +1 @@
|
||||
2d14371febb308fe8d92ab3497dbba8df297912566754fcc1723980824ea3cd7
|
||||
8186e9cfb58fedf1add5288eb30010b8a376dd3dbd2aee39da5ddf067f5b0aae
|
||||
+1
-1
@@ -1 +1 @@
|
||||
7a7cf4af3a6fe381ae4e3046116a0d5a5f3996d4df7f4cab1c35852c52a489e6
|
||||
75d6e447d1d54ad254845b423c38d3c395f07f2e31ee2dd376edc1ed7079ae06
|
||||
@@ -416,6 +416,9 @@ mod imp {
|
||||
pub fn clear_file_decorations(set: &str) -> Result<(), Error> {
|
||||
wit::decorations::clear_file(set).map_err(error)
|
||||
}
|
||||
pub fn set_file_note(path: &str, set: &str, note: &str, tooltip: Option<&str>) -> Result<(), Error> {
|
||||
wit::decorations::set_file_note(path, set, note, tooltip).map_err(error)
|
||||
}
|
||||
pub fn vcs_log(p: &ProjectRes, path: Option<&str>, limit: u32) -> Result<Vec<CommitInfo>, Error> {
|
||||
wit::vcs::log(p, path, limit)
|
||||
.map(|v| {
|
||||
@@ -1842,6 +1845,11 @@ pub fn set_file_decoration(path: &str, set: &str, item: &FileDecoration) -> Resu
|
||||
pub fn clear_file_decorations(set: &str) -> Result<(), Error> {
|
||||
imp::clear_file_decorations(set)
|
||||
}
|
||||
/// Set a note shown after a file's name in the project tree, replacing this tree set's
|
||||
/// annotation for the file (API 1.7). One line of at most 200 characters. Requires project.read.
|
||||
pub fn set_file_note(path: &str, set: &str, note: &str, tooltip: Option<&str>) -> Result<(), Error> {
|
||||
imp::set_file_note(path, set, note, tooltip)
|
||||
}
|
||||
|
||||
/// Starts an owned run configuration in the invoking window. Its id receives run-exited.
|
||||
pub fn start_run(config: &str, args: &[String], debug: bool) -> Result<String, Error> {
|
||||
|
||||
@@ -156,6 +156,7 @@ struct State {
|
||||
restricted: bool,
|
||||
decorations: BTreeMap<(String, String), Vec<Decoration>>,
|
||||
file_decorations: BTreeMap<(String, String), FileDecoration>,
|
||||
file_notes: BTreeMap<(String, String), (String, Option<String>)>,
|
||||
revealed_ranges: Vec<Range>,
|
||||
loopback_queries: VecDeque<Option<String>>,
|
||||
net: Option<NetHandler>,
|
||||
@@ -300,6 +301,10 @@ impl MockHost {
|
||||
pub fn file_decorations(&self) -> BTreeMap<(String, String), FileDecoration> {
|
||||
self.state.borrow().file_decorations.clone()
|
||||
}
|
||||
/// `(set, path)` → `(note, tooltip)` set with `set_file_note`.
|
||||
pub fn file_notes(&self) -> BTreeMap<(String, String), (String, Option<String>)> {
|
||||
self.state.borrow().file_notes.clone()
|
||||
}
|
||||
/// Ranges requested to scroll into view.
|
||||
pub fn revealed_ranges(&self) -> Vec<Range> {
|
||||
self.state.borrow().revealed_ranges.clone()
|
||||
@@ -1655,9 +1660,9 @@ pub mod current {
|
||||
let mut next = s.file_decorations.clone();
|
||||
next.remove(&(set.into(), path.clone()));
|
||||
if style(&item.style) {
|
||||
next.insert((set.into(), path), item.clone());
|
||||
next.insert((set.into(), path.clone()), item.clone());
|
||||
}
|
||||
let names: BTreeSet<_> = next.keys().map(|(set, _)| set).collect();
|
||||
let names: BTreeSet<_> = next.keys().chain(s.file_notes.keys()).map(|(set, _)| set).collect();
|
||||
if set.is_empty()
|
||||
|| set.len() > 128
|
||||
|| names.len() > 50
|
||||
@@ -1666,6 +1671,7 @@ pub mod current {
|
||||
return Err(Error::Invalid("file decoration limit".into()));
|
||||
}
|
||||
s.file_decorations = next;
|
||||
s.file_notes.remove(&(set.into(), path));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
@@ -1673,6 +1679,28 @@ pub mod current {
|
||||
with(|s| {
|
||||
require(s, "project.read")?;
|
||||
s.file_decorations.retain(|(id, _), _| id != set);
|
||||
s.file_notes.retain(|(id, _), _| id != set);
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
pub fn set_file_note(path: &str, set: &str, note: &str, tooltip: Option<&str>) -> Result<(), Error> {
|
||||
with(|s| {
|
||||
require(s, "project.read")?;
|
||||
let path = decoration_path(s, path)?;
|
||||
let key = (set.to_string(), path);
|
||||
let names: BTreeSet<_> =
|
||||
s.file_decorations.keys().chain(s.file_notes.keys()).chain([&key]).map(|(set, _)| set).collect();
|
||||
if set.is_empty()
|
||||
|| set.len() > 128
|
||||
|| names.len() > 50
|
||||
|| note.trim().is_empty()
|
||||
|| note.chars().count() > 200
|
||||
|| note.contains(['\n', '\r'])
|
||||
{
|
||||
return Err(Error::Invalid("a file note is one non-empty line of at most 200 characters".into()));
|
||||
}
|
||||
s.file_decorations.remove(&key);
|
||||
s.file_notes.insert(key, (note.into(), tooltip.map(Into::into)));
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -67,6 +67,14 @@ fn decorations_replace_clear_validate_styles_badges_paths_and_limits() {
|
||||
host::set_file_decoration("a.txt", "test", &file("😀a")).unwrap();
|
||||
host::clear_file_decorations("test").unwrap();
|
||||
assert!(mock.file_decorations().is_empty());
|
||||
host::set_file_decoration("a.txt", "notes", &file("A")).unwrap();
|
||||
host::set_file_note("a.txt", "notes", "entry point", Some("why")).unwrap();
|
||||
assert!(mock.file_decorations().is_empty(), "a note replaces the set's annotation");
|
||||
assert_eq!(mock.file_notes().values().next(), Some(&("entry point".to_string(), Some("why".to_string()))));
|
||||
assert!(host::set_file_note("a.txt", "notes", "two\nlines", None).is_err());
|
||||
assert!(host::set_file_note("a.txt", "notes", &"x".repeat(201), None).is_err());
|
||||
host::clear_file_decorations("notes").unwrap();
|
||||
assert!(mock.file_notes().is_empty());
|
||||
for i in 0..50 {
|
||||
host::set_decorations("a.txt", &format!("set{i}"), &[]).unwrap();
|
||||
}
|
||||
|
||||
@@ -19,4 +19,7 @@ interface decorations {
|
||||
set-file: func(path: string, set-id: string, item: file-decoration) -> result<_, error>;
|
||||
/// Remove this tree set from every file/project.
|
||||
clear-file: func(set-id: string) -> result<_, error>;
|
||||
/// Replace this set's tree annotation for a file with a note shown after its name (API 1.7):
|
||||
/// one line of at most 200 characters, with an optional tooltip.
|
||||
set-file-note: func(path: string, set-id: string, note: string, tooltip: option<string>) -> result<_, error>;
|
||||
}
|
||||
@@ -4932,6 +4932,8 @@ export type FileDecoration = {
|
||||
badge: string | null,
|
||||
style: string,
|
||||
tooltip: string | null,
|
||||
/** Text shown after the name (API 1.7 `set-file-note`). */
|
||||
note?: string | null,
|
||||
};
|
||||
|
||||
export type FileEdit = { kind: "edit"; path: IpcPath; edits: TextEdit[];
|
||||
|
||||
@@ -66,6 +66,19 @@ it("filters project roots and unknown styles and replaces tree badges", () => {
|
||||
expect(getFileDecoration("/p/a.txt")?.badge).toBeUndefined();
|
||||
});
|
||||
|
||||
it("shows a tree note after the name without colouring the file", () => {
|
||||
const note = {
|
||||
...set(),
|
||||
tree: true,
|
||||
items: [],
|
||||
file: { style: "", badge: null, tooltip: "why", note: "entry point" },
|
||||
};
|
||||
setPluginDecorations("test", [note]);
|
||||
expect(getFileDecoration("/p/a.txt")).toMatchObject({ suffix: [{ text: "entry point" }], tooltip: "why" });
|
||||
expect(getFileDecoration("/p/a.txt")?.color).toBeUndefined();
|
||||
setPluginDecorations("test", []);
|
||||
});
|
||||
|
||||
it("selects UTF-16 ranges and reveals without changing text", () => {
|
||||
handleRuntimeEvent({ type: "editorRanges", path: ctx.path, ranges: [range], reveal: false });
|
||||
expect(editor.view.state.selection.main.from).toBe(2);
|
||||
|
||||
@@ -32,13 +32,15 @@ function currentSets(sets: DecorationSet[]) {
|
||||
function updateTree(plugin: string, sets: DecorationSet[]) {
|
||||
const items = new Map<string, FileDecoration>();
|
||||
for (const s of currentSets(sets))
|
||||
if (s.tree && s.file && Object.hasOwn(colors, s.file.style)) {
|
||||
if (s.tree && s.file && (Object.hasOwn(colors, s.file.style) || s.file.note)) {
|
||||
items.set(s.path, {
|
||||
color: colors[s.file.style],
|
||||
color: Object.hasOwn(colors, s.file.style) ? colors[s.file.style] : undefined,
|
||||
badge: s.file.badge ?? undefined,
|
||||
tooltip: s.file.tooltip ?? undefined,
|
||||
faded: s.file.style === "muted",
|
||||
error: s.file.style === "error",
|
||||
// A note: muted text after the name, like the VCS branch of a root.
|
||||
suffix: s.file.note ? [{ text: s.file.note }] : undefined,
|
||||
});
|
||||
}
|
||||
setFileDecorations(`plugin:${plugin}`, items);
|
||||
|
||||
@@ -19,4 +19,7 @@ interface decorations {
|
||||
set-file: func(path: string, set-id: string, item: file-decoration) -> result<_, error>;
|
||||
/// Remove this tree set from every file/project.
|
||||
clear-file: func(set-id: string) -> result<_, error>;
|
||||
/// Replace this set's tree annotation for a file with a note shown after its name (API 1.7):
|
||||
/// one line of at most 200 characters, with an optional tooltip.
|
||||
set-file-note: func(path: string, set-id: string, note: string, tooltip: option<string>) -> result<_, error>;
|
||||
}
|
||||
Reference in new issue
Block a user