Files
openidea/src/features/tools/LanguageServersPage.module.css
T
l0ng-ai 03a660354c feat(tools): Custom language server paths and a list/details Language Servers page
Servers and debug adapters could only be found on PATH or in the IDE's
tools folder; the only way to pick another executable (a version that
matches the project's Elixir/OTP, a local build) was an undocumented
languages/*.toml override. `tools.<command>.path` now names the
executable to launch: language servers (configure_server, restarted on
change), debug sessions and the tool list honour it, the latter
reporting a Custom status with its version or why the path is unusable.

The Language Servers page is laid out like Plugins: a compact list
grouped by availability on the left, the selected tool's command, path,
location, version, install actions and hints on the right.

A debugger named like its language server (ElixirLS's elixir-ls /
elixir-ls-debugger) was folded into the server's row and never listed;
it now gets a row of its own.

Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
2026-10-24 11:26:31 +08:00

281 lines
4.7 KiB
CSS

.page {
display: flex;
flex-direction: column;
gap: 8px;
min-width: 0;
height: 100%;
min-height: 420px;
}
.intro {
margin: 0;
max-width: 680px;
color: var(--fg-secondary);
}
.body {
display: flex;
flex: 1;
min-height: 0;
border-radius: var(--radius-small);
box-shadow: inset 0 0 0 1px var(--border);
overflow: hidden;
}
/* list */
.side {
display: flex;
flex: none;
flex-direction: column;
width: 300px;
min-height: 0;
border-right: 1px solid var(--border);
}
.toolbar {
display: flex;
align-items: center;
gap: 4px;
margin: 8px 8px 6px;
}
.search {
flex: 1;
min-width: 0;
}
.segmented {
display: flex;
height: var(--h-control-small);
margin: 0 8px 6px;
border-radius: var(--radius-small);
box-shadow: inset 0 0 0 1px var(--border-strong);
overflow: hidden;
}
.segment {
flex: 1;
padding: 0 6px;
border: 0;
background: transparent;
color: var(--fg-secondary);
font: inherit;
white-space: nowrap;
}
.segment:hover {
background: var(--bg-hover);
}
.segment:focus-visible {
outline: 2px solid var(--accent);
outline-offset: -2px;
}
.segmentOn {
background: var(--bg-selected);
color: var(--fg-strong);
}
.list {
flex: 1;
min-height: 0;
margin: 0;
padding: 0 0 4px;
list-style: none;
overflow: auto;
}
.groupHeader {
display: flex;
align-items: center;
gap: 6px;
height: var(--h-row);
padding: 0 12px;
color: var(--fg-muted);
font-size: var(--fs-small);
}
.groupCount {
font-variant-numeric: tabular-nums;
}
.row:hover {
background: var(--bg-hover);
}
.rowSelected,
.rowSelected:hover {
background: var(--bg-selected);
}
.rowMain {
display: flex;
align-items: center;
gap: 8px;
width: 100%;
height: var(--h-row);
padding: 0 12px;
border: 0;
background: transparent;
color: var(--fg);
font: inherit;
text-align: left;
}
.rowMain:focus-visible {
outline: 2px solid var(--accent);
outline-offset: -2px;
}
.rowName {
flex: none;
max-width: 60%;
overflow: hidden;
color: var(--fg-strong);
text-overflow: ellipsis;
white-space: nowrap;
}
.rowLanguages {
flex: 1;
min-width: 0;
overflow: hidden;
color: var(--fg-muted);
font-size: var(--fs-small);
text-align: right;
text-overflow: ellipsis;
white-space: nowrap;
}
.kindTag {
flex: none;
padding: 0 5px;
border-radius: var(--radius-small);
background: var(--bg-control);
color: var(--fg-muted);
font-size: var(--fs-tiny);
line-height: 16px;
}
.listEmpty {
padding: 8px 12px;
color: var(--fg-muted);
}
/* details */
.details {
display: flex;
flex: 1;
flex-direction: column;
gap: 10px;
min-width: 0;
padding: 12px 16px 16px;
overflow: auto;
}
.detailsEmpty {
flex: 1;
}
.header {
display: flex;
align-items: flex-start;
gap: 12px;
}
.headerText {
min-width: 0;
}
.title {
display: flex;
align-items: center;
gap: 8px;
color: var(--fg-strong);
font-size: var(--fs-input-large);
font-weight: 600;
}
.subtitle {
margin-top: 2px;
color: var(--fg-secondary);
}
.actions {
display: flex;
align-items: center;
gap: 4px;
}
.fields {
display: grid;
grid-template-columns: max-content minmax(0, 1fr);
column-gap: 16px;
row-gap: 8px;
align-items: baseline;
margin-top: 4px;
}
.field {
display: contents;
}
.fieldLabel {
color: var(--fg-secondary);
}
.fieldValue {
min-width: 0;
color: var(--fg);
}
code.fieldValue {
font-family: var(--font-mono);
font-size: var(--fs-small);
}
.breakAll {
overflow-wrap: anywhere;
}
.version {
font-variant-numeric: tabular-nums;
}
.pathRow {
display: flex;
align-items: center;
gap: 4px;
}
.pathInput {
flex: 1;
min-width: 0;
}
.fieldHint {
margin-top: 2px;
color: var(--fg-muted);
font-size: var(--fs-small);
}
.fieldError,
.error {
color: var(--danger);
overflow-wrap: anywhere;
}
.fieldError {
margin-top: 2px;
font-size: var(--fs-small);
}
.notice {
padding: 6px 8px;
border-radius: var(--radius-small);
background: var(--bg-control);
color: var(--fg-secondary);
overflow-wrap: anywhere;
-webkit-user-select: text;
user-select: text;
}
.job {
display: flex;
flex-direction: column;
gap: 4px;
}
.jobBar {
width: 100%;
}
.jobLine {
display: flex;
align-items: center;
gap: 8px;
}
.jobMessage {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--fg-muted);
font-family: var(--font-mono);
font-size: var(--fs-small);
}
.log {
margin: 0;
padding: 6px 8px;
max-height: 240px;
overflow: auto;
background: var(--bg-app);
color: var(--fg-secondary);
border-radius: var(--radius-small);
font-family: var(--font-mono);
font-size: var(--fs-small);
white-space: pre-wrap;
-webkit-user-select: text;
user-select: text;
}