@@ -1,94 +0,0 @@
-use editor::Editor;
-use gpui::{
- elements::*,
- platform::{CursorStyle, MouseButton},
- Entity, Subscription, View, ViewContext, ViewHandle, WeakViewHandle,
-};
-use std::sync::Arc;
-use workspace::{item::ItemHandle, StatusItemView, Workspace};
-
-pub struct ActiveBufferLanguage {
- active_language: Option<Option<Arc<str>>>,
- workspace: WeakViewHandle<Workspace>,
- _observe_active_editor: Option<Subscription>,
-}
-
-impl ActiveBufferLanguage {
- pub fn new(workspace: &Workspace) -> Self {
- Self {
- active_language: None,
- workspace: workspace.weak_handle(),
- _observe_active_editor: None,
- }
- }
-
- fn update_language(&mut self, editor: ViewHandle<Editor>, cx: &mut ViewContext<Self>) {
- self.active_language = Some(None);
-
- let editor = editor.read(cx);
- if let Some((_, buffer, _)) = editor.active_excerpt(cx) {
- if let Some(language) = buffer.read(cx).language() {
- self.active_language = Some(Some(language.name()));
- }
- }
-
- cx.notify();
- }
-}
-
-impl Entity for ActiveBufferLanguage {
- type Event = ();
-}
-
-impl View for ActiveBufferLanguage {
- fn ui_name() -> &'static str {
- "ActiveBufferLanguage"
- }
-
- fn render(&mut self, cx: &mut ViewContext<Self>) -> AnyElement<Self> {
- if let Some(active_language) = self.active_language.as_ref() {
- let active_language_text = if let Some(active_language_text) = active_language {
- active_language_text.to_string()
- } else {
- "Unknown".to_string()
- };
-
- MouseEventHandler::new::<Self, _>(0, cx, |state, cx| {
- let theme = &theme::current(cx).workspace.status_bar;
- let style = theme.active_language.style_for(state);
- Label::new(active_language_text, style.text.clone())
- .contained()
- .with_style(style.container)
- })
- .with_cursor_style(CursorStyle::PointingHand)
- .on_click(MouseButton::Left, |_, this, cx| {
- if let Some(workspace) = this.workspace.upgrade(cx) {
- workspace.update(cx, |workspace, cx| {
- crate::toggle(workspace, &Default::default(), cx)
- });
- }
- })
- .into_any()
- } else {
- Empty::new().into_any()
- }
- }
-}
-
-impl StatusItemView for ActiveBufferLanguage {
- fn set_active_pane_item(
- &mut self,
- active_pane_item: Option<&dyn ItemHandle>,
- cx: &mut ViewContext<Self>,
- ) {
- if let Some(editor) = active_pane_item.and_then(|item| item.act_as::<Editor>(cx)) {
- self._observe_active_editor = Some(cx.observe(&editor, Self::update_language));
- self.update_language(editor, cx);
- } else {
- self.active_language = None;
- self._observe_active_editor = None;
- }
-
- cx.notify();
- }
-}
@@ -1,196 +0,0 @@
-mod active_buffer_language;
-
-pub use active_buffer_language::ActiveBufferLanguage;
-use anyhow::anyhow;
-use editor::Editor;
-use fuzzy::{match_strings, StringMatch, StringMatchCandidate};
-use gpui::{actions, elements::*, AppContext, ModelHandle, MouseState, ViewContext};
-use language::{Buffer, LanguageRegistry};
-use picker::{Picker, PickerDelegate, PickerEvent};
-use project::Project;
-use std::sync::Arc;
-use util::ResultExt;
-use workspace::Workspace;
-
-actions!(language_selector, [Toggle]);
-
-pub fn init(cx: &mut AppContext) {
- Picker::<LanguageSelectorDelegate>::init(cx);
- cx.add_action(toggle);
-}
-
-pub fn toggle(
- workspace: &mut Workspace,
- _: &Toggle,
- cx: &mut ViewContext<Workspace>,
-) -> Option<()> {
- let (_, buffer, _) = workspace
- .active_item(cx)?
- .act_as::<Editor>(cx)?
- .read(cx)
- .active_excerpt(cx)?;
- workspace.toggle_modal(cx, |workspace, cx| {
- let registry = workspace.app_state().languages.clone();
- cx.add_view(|cx| {
- Picker::new(
- LanguageSelectorDelegate::new(buffer, workspace.project().clone(), registry),
- cx,
- )
- })
- });
- Some(())
-}
-
-pub struct LanguageSelectorDelegate {
- buffer: ModelHandle<Buffer>,
- project: ModelHandle<Project>,
- language_registry: Arc<LanguageRegistry>,
- candidates: Vec<StringMatchCandidate>,
- matches: Vec<StringMatch>,
- selected_index: usize,
-}
-
-impl LanguageSelectorDelegate {
- fn new(
- buffer: ModelHandle<Buffer>,
- project: ModelHandle<Project>,
- language_registry: Arc<LanguageRegistry>,
- ) -> Self {
- let candidates = language_registry
- .language_names()
- .into_iter()
- .enumerate()
- .map(|(candidate_id, name)| StringMatchCandidate::new(candidate_id, name))
- .collect::<Vec<_>>();
- let mut matches = candidates
- .iter()
- .map(|candidate| StringMatch {
- candidate_id: candidate.id,
- score: 0.,
- positions: Default::default(),
- string: candidate.string.clone(),
- })
- .collect::<Vec<_>>();
- matches.sort_unstable_by(|mat1, mat2| mat1.string.cmp(&mat2.string));
-
- Self {
- buffer,
- project,
- language_registry,
- candidates,
- matches,
- selected_index: 0,
- }
- }
-}
-
-impl PickerDelegate for LanguageSelectorDelegate {
- fn placeholder_text(&self) -> Arc<str> {
- "Select a language...".into()
- }
-
- fn match_count(&self) -> usize {
- self.matches.len()
- }
-
- fn confirm(&mut self, _: bool, cx: &mut ViewContext<Picker<Self>>) {
- if let Some(mat) = self.matches.get(self.selected_index) {
- let language_name = &self.candidates[mat.candidate_id].string;
- let language = self.language_registry.language_for_name(language_name);
- let project = self.project.downgrade();
- let buffer = self.buffer.downgrade();
- cx.spawn(|_, mut cx| async move {
- let language = language.await?;
- let project = project
- .upgrade(&cx)
- .ok_or_else(|| anyhow!("project was dropped"))?;
- let buffer = buffer
- .upgrade(&cx)
- .ok_or_else(|| anyhow!("buffer was dropped"))?;
- project.update(&mut cx, |project, cx| {
- project.set_language_for_buffer(&buffer, language, cx);
- });
- anyhow::Ok(())
- })
- .detach_and_log_err(cx);
- }
-
- cx.emit(PickerEvent::Dismiss);
- }
-
- fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
-
- fn selected_index(&self) -> usize {
- self.selected_index
- }
-
- fn set_selected_index(&mut self, ix: usize, _: &mut ViewContext<Picker<Self>>) {
- self.selected_index = ix;
- }
-
- fn update_matches(
- &mut self,
- query: String,
- cx: &mut ViewContext<Picker<Self>>,
- ) -> gpui::Task<()> {
- let background = cx.background().clone();
- let candidates = self.candidates.clone();
- cx.spawn(|this, mut cx| async move {
- let matches = if query.is_empty() {
- candidates
- .into_iter()
- .enumerate()
- .map(|(index, candidate)| StringMatch {
- candidate_id: index,
- string: candidate.string,
- positions: Vec::new(),
- score: 0.0,
- })
- .collect()
- } else {
- match_strings(
- &candidates,
- &query,
- false,
- 100,
- &Default::default(),
- background,
- )
- .await
- };
-
- this.update(&mut cx, |this, cx| {
- let delegate = this.delegate_mut();
- delegate.matches = matches;
- delegate.selected_index = delegate
- .selected_index
- .min(delegate.matches.len().saturating_sub(1));
- cx.notify();
- })
- .log_err();
- })
- }
-
- fn render_match(
- &self,
- ix: usize,
- mouse_state: &mut MouseState,
- selected: bool,
- cx: &AppContext,
- ) -> AnyElement<Picker<Self>> {
- let theme = theme::current(cx);
- let mat = &self.matches[ix];
- let style = theme.picker.item.in_state(selected).style_for(mouse_state);
- let buffer_language_name = self.buffer.read(cx).language().map(|l| l.name());
- let mut label = mat.string.clone();
- if buffer_language_name.as_deref() == Some(mat.string.as_str()) {
- label.push_str(" (current)");
- }
-
- Label::new(label, style.label.clone())
- .with_highlights(mat.positions.clone())
- .contained()
- .with_style(style.container)
- .into_any()
- }
-}