Skip to content

Commit 195dc3e

Browse files
Show languages in the docs sidebar (#2859)
So far our implementation of scope facets have been lacking and therefore we made the decision to hide languages in the docs sidebar. Now our support for scope facets in the most common languages is quite good so I would like to show languages.
1 parent f0526d5 commit 195dc3e

40 files changed

+263
-122
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
tags: [documentation]
3+
pullRequest: 2859
4+
---
5+
6+
- Added languages sidebar to documents page. Here you can see the supported scope facets for each language.

packages/common/src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export * from "./types/TreeSitter";
9393
export * from "./types/tutorial.types";
9494
export * from "./util";
9595
export * from "./util/camelCaseToAllDown";
96+
export * from "./util/capitalize";
9697
export * from "./util/clientSupportsFallback";
9798
export * from "./util/CompositeKeyDefaultMap";
9899
export * from "./util/CompositeKeyMap";
+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export function capitalize(str: string) {
2+
return str.charAt(0).toUpperCase() + str.slice(1);
3+
}

packages/cursorless-org-docs/src/css/custom.css

+20
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,23 @@
2828
.hidden {
2929
display: none;
3030
}
31+
32+
.card {
33+
border: 1px solid rgba(0, 0, 0, 0.175);
34+
margin-bottom: 1rem;
35+
}
36+
37+
.card-header {
38+
background-color: #f8f9fa;
39+
border-bottom: 1px solid rgba(0, 0, 0, 0.125);
40+
padding: 0.5rem 1rem;
41+
cursor: pointer;
42+
}
43+
44+
.card-body {
45+
padding: 1rem;
46+
}
47+
48+
.facet-name {
49+
font-weight: 600;
50+
}

packages/cursorless-org-docs/src/docs/user/languages/ScopeSupport.tsx

-82
This file was deleted.

packages/cursorless-org-docs/src/docs/user/languages/_category_.json

-3
This file was deleted.

packages/cursorless-org-docs/src/docs/user/languages/c.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Language from "./Language";
1+
import { Language } from "./components/Language";
22

33
# C
44

packages/cursorless-org-docs/src/docs/user/languages/clojure.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Language from "./Language";
1+
import { Language } from "./components/Language";
22

33
# Clojure
44

Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import React from "react";
2-
import ScopeSupport from "./ScopeSupport";
2+
import { ScopeSupport } from "./ScopeSupport";
33

44
interface Props {
55
languageId: string;
66
}
77

8-
export default function Language({ languageId }: Props) {
8+
export function Language({ languageId }: Props) {
99
return <ScopeSupport languageId={languageId} />;
1010
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import {
2+
ScopeSupportFacetLevel,
3+
languageScopeSupport,
4+
scopeSupportFacets,
5+
} from "@cursorless/common";
6+
import React from "react";
7+
import { ScopeSupportForLevel } from "./ScopeSupportForLevel";
8+
9+
interface Props {
10+
languageId: string;
11+
}
12+
13+
export function ScopeSupport({ languageId }: Props): JSX.Element {
14+
const scopesSorted = [...scopeSupportFacets].sort();
15+
const scopeSupport = languageScopeSupport[languageId] ?? {};
16+
17+
const supportedScopes = scopesSorted.filter(
18+
(facet) => scopeSupport[facet] === ScopeSupportFacetLevel.supported,
19+
);
20+
const supportedLegacyScopes = scopesSorted.filter(
21+
(facet) => scopeSupport[facet] === ScopeSupportFacetLevel.supportedLegacy,
22+
);
23+
const unsupportedScopes = scopesSorted.filter(
24+
(facet) => scopeSupport[facet] === ScopeSupportFacetLevel.unsupported,
25+
);
26+
const unspecifiedScopes = scopesSorted.filter(
27+
(facet) => scopeSupport[facet] == null,
28+
);
29+
30+
return (
31+
<>
32+
<h2>Scopes</h2>
33+
34+
<ScopeSupportForLevel
35+
facets={supportedScopes}
36+
title="Supported facets"
37+
subtitle="These facets are supported"
38+
expanded
39+
/>
40+
41+
<ScopeSupportForLevel
42+
facets={supportedLegacyScopes}
43+
title="Supported Legacy facets"
44+
subtitle="These facets are supported with the legacy implementation and should be migrated to the new implementation"
45+
/>
46+
47+
<ScopeSupportForLevel
48+
facets={unsupportedScopes}
49+
title="Unsupported facets"
50+
subtitle="These facets are not supported yet and needs a developer to implement them"
51+
description={
52+
<>
53+
We would happily accept{" "}
54+
<a href="https://www.cursorless.org/docs/contributing/adding-a-new-scope">
55+
contributions
56+
</a>
57+
</>
58+
}
59+
/>
60+
61+
<ScopeSupportForLevel
62+
facets={unspecifiedScopes}
63+
title="Unspecified facets"
64+
subtitle="These facets are unspecified"
65+
description={
66+
<>
67+
Note that in many instances we actually do support these scopes and
68+
facets, but we have not yet updated 'languageScopeSupport' to
69+
reflect this fact.
70+
<br />
71+
We would happily accept{" "}
72+
<a href="https://www.cursorless.org/docs/contributing/adding-a-new-scope">
73+
contributions
74+
</a>
75+
</>
76+
}
77+
/>
78+
</>
79+
);
80+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import {
2+
camelCaseToAllDown,
3+
capitalize,
4+
groupBy,
5+
type ScopeSupportFacet,
6+
type ScopeSupportFacetInfo,
7+
scopeSupportFacetInfos,
8+
type ScopeType,
9+
type SimpleScopeTypeType,
10+
} from "@cursorless/common";
11+
import React, { useState } from "react";
12+
13+
interface Props {
14+
facets: ScopeSupportFacet[];
15+
title: string;
16+
subtitle: string;
17+
description?: React.ReactNode;
18+
expanded?: boolean;
19+
}
20+
21+
export function ScopeSupportForLevel({
22+
facets,
23+
title,
24+
subtitle,
25+
description,
26+
expanded: expandedProp,
27+
}: Props): JSX.Element | null {
28+
const [expanded, setExpanded] = useState(expandedProp ?? false);
29+
30+
if (facets.length === 0) {
31+
return null;
32+
}
33+
34+
const renderBody = () => {
35+
if (!expanded) {
36+
return null;
37+
}
38+
39+
const facetInfos = facets.map(
40+
(facet): AugmentedFacetInfo => ({
41+
facet,
42+
...scopeSupportFacetInfos[facet],
43+
}),
44+
);
45+
const scopeGroups: Map<string, AugmentedFacetInfo[]> = groupBy(
46+
facetInfos,
47+
(facetInfo) => serializeScopeType(facetInfo.scopeType),
48+
);
49+
const scopeTypes = Array.from(scopeGroups.keys()).sort();
50+
51+
return (
52+
<div className="card-body">
53+
{description && <p>{description}</p>}
54+
55+
{scopeTypes.map((scopeType) => {
56+
const facetInfos = scopeGroups.get(scopeType) ?? [];
57+
return (
58+
<div key={scopeType}>
59+
<h4>{prettifyScopeType(scopeType)}</h4>
60+
<ul>
61+
{facetInfos.map((facetInfo) => {
62+
return (
63+
<li key={facetInfo.facet}>
64+
<span className="facet-name" title={facetInfo.facet}>
65+
{prettifyFacet(facetInfo.facet)}
66+
</span>
67+
: {facetInfo.description}
68+
</li>
69+
);
70+
})}
71+
</ul>
72+
</div>
73+
);
74+
})}
75+
</div>
76+
);
77+
};
78+
79+
return (
80+
<div className="card">
81+
<div className="card-header" onClick={() => setExpanded(!expanded)}>
82+
<h3>{title}</h3>
83+
{subtitle}
84+
</div>
85+
86+
{renderBody()}
87+
</div>
88+
);
89+
}
90+
91+
interface AugmentedFacetInfo extends ScopeSupportFacetInfo {
92+
facet: ScopeSupportFacet;
93+
}
94+
95+
function prettifyScopeType(scopeType: string): string {
96+
return capitalize(camelCaseToAllDown(scopeType));
97+
}
98+
99+
function prettifyFacet(facet: ScopeSupportFacet): string {
100+
const parts = facet.split(".").map(camelCaseToAllDown);
101+
if (parts.length === 1) {
102+
return capitalize(parts[0]);
103+
}
104+
const isIteration = parts[parts.length - 1] === "iteration";
105+
if (isIteration) {
106+
parts.pop();
107+
}
108+
const name = capitalize(parts.slice(1).join(" "));
109+
return isIteration ? `${name} (iteration)` : name;
110+
}
111+
112+
function serializeScopeType(
113+
scopeType: SimpleScopeTypeType | ScopeType,
114+
): string {
115+
if (typeof scopeType === "string") {
116+
return scopeType;
117+
}
118+
return scopeType.type;
119+
}

packages/cursorless-org-docs/src/docs/user/languages/cpp.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Language from "./Language";
1+
import { Language } from "./components/Language";
22

33
# C++
44

packages/cursorless-org-docs/src/docs/user/languages/csharp.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Language from "./Language";
1+
import { Language } from "./components/Language";
22

33
# C#
44

packages/cursorless-org-docs/src/docs/user/languages/css.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Language from "./Language";
1+
import { Language } from "./components/Language";
22

33
# CSS
44

Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import Language from "./Language";
1+
import { Language } from "./components/Language";
22

3-
# dart
3+
# Dart
44

55
<Language languageId="dart"></Language>

packages/cursorless-org-docs/src/docs/user/languages/go.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Language from "./Language";
1+
import { Language } from "./components/Language";
22

33
# Go
44

packages/cursorless-org-docs/src/docs/user/languages/html.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Language from "./Language";
1+
import { Language } from "./components/Language";
22

33
# HTML
44

packages/cursorless-org-docs/src/docs/user/languages/java.mdx

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Language from "./Language";
1+
import { Language } from "./components/Language";
22

33
# Java
44

0 commit comments

Comments
 (0)