Make gr.Code support lines, expand to fill entire element (#3651)

* Make `gr.Code` support `lines`, expand to fill entire element

* Update changelog

* Fix typeerrors

* Fix test

* fix interactive bug with update

---------

Co-authored-by: Abubakar Abid <abubakar@huggingface.co>
Co-authored-by: aliabd <ali.si3luwa@gmail.com>
Co-authored-by: pngwn <hello@pngwn.io>
This commit is contained in:
space-nuko 2023-04-06 10:52:57 -04:00 committed by GitHub
parent c0d70a7af5
commit ebfce0f784
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 9 deletions

View File

@ -102,6 +102,7 @@ By [@freddyaboulton](https://github.com/freddyaboulton) in [PR 3581](https://git
- Fixed bug where textbox shrinks when `lines` set to larger than 20 by [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3637](https://github.com/gradio-app/gradio/pull/3637)
- Ensure CSS has fully loaded before rendering the application, by [@pngwn](https://github.com/pngwn) in [PR 3573](https://github.com/gradio-app/gradio/pull/3573)
- Support using an empty list as `gr.Dataframe` value, by [@space-nuko](https://github.com/space-nuko) in [PR 3646](https://github.com/gradio-app/gradio/pull/3646)
- Make `gr.Code` support the `lines` property, by [@space-nuko](https://github.com/space-nuko) in [PR 3651](https://github.com/gradio-app/gradio/pull/3651)
- Fixes certain `_js` return values being double wrapped in an array, by [@space-nuko](https://github.com/space-nuko) in [PR 3594](https://github.com/gradio-app/gradio/pull/3594)
- Correct the documentation of `gr.File` component to state that its preprocessing method converts the uploaded file to a temporary file, by @RussellLuo in [PR 3660](https://github.com/gradio-app/gradio/pull/3660)
- Fixed bug in Serializer ValueError text by [@osanseviero](https://github.com/osanseviero) in [PR 3669](https://github.com/gradio-app/gradio/pull/3669)

View File

@ -5336,7 +5336,7 @@ class BarPlot(Plot):
width: int | None = None,
y_lim: List[int] | None = None,
caption: str | None = None,
interactive: bool | None = True,
interactive: bool | None = None,
label: str | None = None,
show_label: bool = True,
visible: bool = True,
@ -5635,6 +5635,7 @@ class Code(Changeable, IOComponent, StringSerializable):
value: str | Tuple[str] | None = None,
language: str | None = None,
*,
lines: int = 5,
label: str | None = None,
interactive: bool | None = None,
show_label: bool = True,
@ -5656,6 +5657,7 @@ class Code(Changeable, IOComponent, StringSerializable):
"""
assert language in Code.languages, f"Language {language} not supported."
self.language = language
self.lines = lines
IOComponent.__init__(
self,
label=label,
@ -5672,6 +5674,7 @@ class Code(Changeable, IOComponent, StringSerializable):
return {
"value": self.value,
"language": self.language,
"lines": self.lines,
**IOComponent.get_config(self),
}
@ -5695,7 +5698,7 @@ class Code(Changeable, IOComponent, StringSerializable):
show_label: bool | None = None,
visible: bool | None = None,
language: str | None = None,
interactive: bool | None = True,
interactive: bool | None = None,
):
return {
"label": label,

View File

@ -17,6 +17,7 @@
export let value: string = "";
export let language: string = "";
export let lines: number = 5;
export let target: HTMLElement;
export let elem_id: string = "";
export let elem_classes: Array<string> = [];
@ -44,7 +45,7 @@
{:else}
<Widget {language} {value} />
<Code bind:value {language} {dark_mode} readonly />
<Code bind:value {language} {lines} {dark_mode} readonly />
{/if}
</Block>
{:else}
@ -53,7 +54,7 @@
<BlockLabel Icon={CodeIcon} {show_label} {label} float={false} />
<Code bind:value {language} {dark_mode} />
<Code bind:value {language} {lines} {dark_mode} />
</Block>
{/if}

View File

@ -20,6 +20,7 @@
export let basic = true;
export let language: string;
export let lines: number = 5;
export let extensions: Extension[] = [];
export let useTab = true;
@ -41,6 +42,7 @@
$: reconfigure(), lang_extension;
$: setDoc(value);
$: updateLines(lines);
function setDoc(newDoc: string) {
if (view && newDoc !== view.state.doc.toString()) {
@ -54,6 +56,12 @@
}
}
function updateLines(newLines: number) {
if (view) {
view.requestMeasure({ read: updateGutters });
}
}
function createEditorView(): EditorView {
return new EditorView({
parent: element,
@ -61,6 +69,35 @@
});
}
function getGutterLineHeight(view: EditorView): string | null {
let elements = view.dom.querySelectorAll<HTMLElement>(".cm-gutterElement");
if (elements.length === 0) {
return null;
}
for (var i = 0; i < elements.length; i++) {
let node = elements[i];
let height = getComputedStyle(node)?.height ?? "0px";
if (height != "0px") {
return height;
}
}
return null;
}
function updateGutters(view: EditorView): any {
let gutters = view.dom.querySelectorAll<HTMLElement>(".cm-gutter");
let _lines = lines + 1;
let lineHeight = getGutterLineHeight(view);
if (!lineHeight) {
return null;
}
for (var i = 0; i < gutters.length; i++) {
let node = gutters[i];
node.style.minHeight = `calc(${lineHeight} * ${_lines})`;
}
return null;
}
function handleChange(vu: ViewUpdate): void {
if (vu.docChanged) {
const doc = vu.state.doc;
@ -68,6 +105,7 @@
value = text;
dispatch("change", text);
}
view.requestMeasure({ read: updateGutters });
}
function getExtensions() {
@ -98,9 +136,6 @@
fontFamily: "var(--font-mono)",
minHeight: "100%"
},
".cm-gutter": {
minHeight: "231px"
},
".cm-gutters": {
marginRight: "1px",
borderRight: "1px solid var(--border-color-primary)",
@ -176,12 +211,23 @@
</div>
<style>
.wrap {
display: flex;
flex-direction: column;
flex-flow: column;
margin: 0;
padding: 0;
height: 100%;
}
.codemirror-wrapper {
min-height: 250px;
max-height: 480px;
height: 100%;
overflow: auto;
}
:global(.cm-editor) {
height: 100%;
}
/* Dunno why this doesn't work through the theme API -- don't remove*/
:global(.cm-selectionBackground) {
background-color: #b9d2ff30 !important;

View File

@ -2623,6 +2623,7 @@ class TestCode:
assert code.get_config() == {
"value": None,
"language": None,
"lines": 5,
"name": "code",
"show_label": True,
"label": None,