Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Path: blob/master/src/packages/jupyter/util/misc.ts
Views: 687
/*1* This file is part of CoCalc: Copyright © 2020 Sagemath, Inc.2* License: MS-RSL – see LICENSE.md for details3*/45/*6Some simple misc functions with no dependencies.78It's very good to have these as functions rather than put9the code all over the place and have conventions about paths!1011part of CoCalc12(c) SageMath, Inc., 201713*/1415import * as immutable from "immutable";1617import { cmp } from "@cocalc/util/misc";1819// This list is inspired by OutputArea.output_types in https://github.com/jupyter/notebook/blob/master/notebook/static/notebook/js/outputarea.js20// The order matters -- we only keep the left-most type (see import-from-ipynb.coffee)2122export const JUPYTER_MIMETYPES = [23"application/javascript",24"text/html",25"text/markdown",26"text/latex",27"image/svg+xml",28"image/png",29"image/jpeg",30"application/pdf",31"text/plain",32] as const;3334// with metadata.cocalc.priority >= this the kernel will be "emphasized" or "suggested" in the UI35export const KERNEL_POPULAR_THRESHOLD = 10;3637export type Kernel = immutable.Map<string, string>;38export type Kernels = immutable.List<Kernel>;3940export function codemirror_to_jupyter_pos(41code: string,42pos: { ch: number; line: number },43): number {44const lines = code.split("\n");45let s = pos.ch;46for (let i = 0; i < pos.line; i++) {47s += lines[i].length + 1;48}49return s;50}5152// Return s + ... + s = s*n (in python notation), where there are n>=0 summands.53export function times_n(s: string, n: number): string {54let t = "";55for (let i = 0; i < n; i++) t += s;56return t;57}5859// These js_idx functions are adapted from https://github.com/jupyter/notebook/pull/250960// Also, see https://github.com/nteract/hydrogen/issues/807 for why.61// An example using a python3 kernel is to define62// 𨭎𨭎𨭎𨭎𨭎 = 1063// then type 𨭎𨭎[tab key] and see it properly complete.6465// javascript stores text as utf16 and string indices use "code units",66// which stores high-codepoint characters as "surrogate pairs",67// which occupy two indices in the javascript string.68// We need to translate cursor_pos in the protocol (in characters)69// to js offset (with surrogate pairs taking two spots).70export function js_idx_to_char_idx(js_idx: number, text: string): number {71let char_idx = js_idx;72for (let i = 0; i + 1 < text.length && i < js_idx; i++) {73const char_code = text.charCodeAt(i);74// check for surrogate pair75if (char_code >= 0xd800 && char_code <= 0xdbff) {76const next_char_code = text.charCodeAt(i + 1);77if (next_char_code >= 0xdc00 && next_char_code <= 0xdfff) {78char_idx--;79i++;80}81}82}83return char_idx;84}8586export function char_idx_to_js_idx(char_idx: number, text: string): number {87let js_idx = char_idx;88for (let i = 0; i + 1 < text.length && i < js_idx; i++) {89const char_code = text.charCodeAt(i);90// check for surrogate pair91if (char_code >= 0xd800 && char_code <= 0xdbff) {92const next_char_code = text.charCodeAt(i + 1);93if (next_char_code >= 0xdc00 && next_char_code <= 0xdfff) {94js_idx++;95i++;96}97}98}99return js_idx;100}101102// Transforms the KernelSpec list into two useful datastructures.103// Was part of jupyter/store, but now used in several places.104export function get_kernels_by_name_or_language(105kernels: Kernels,106): [107immutable.OrderedMap<string, immutable.Map<string, string>>,108immutable.OrderedMap<string, immutable.List<string>>,109] {110const data_name: any = {};111let data_lang: any = {};112const add_lang = (lang, entry) => {113if (data_lang[lang] == null) data_lang[lang] = [];114data_lang[lang].push(entry);115};116kernels117.filter((entry) => entry.getIn(["metadata", "cocalc", "disabled"]) !== true)118.map((entry) => {119const name = entry.get("name");120const lang = entry.get("language");121if (name != null) data_name[name] = entry;122if (lang == null) {123// we collect all kernels without a language under "misc"124add_lang("misc", entry);125} else {126add_lang(lang, entry);127}128});129const by_name = immutable130.OrderedMap<string, immutable.Map<string, string>>(data_name)131.sortBy((v, k) => {132return v.get("display_name", v.get("name", k)).toLowerCase();133});134// data_lang, we're only interested in the kernel names, not the entry itself135data_lang = immutable.fromJS(data_lang).map((v, k) => {136v = v137.sortBy((v) => v.get("display_name", v.get("name", k)).toLowerCase())138.map((v) => v.get("name"));139return v;140});141const by_lang = immutable142.OrderedMap<string, immutable.List<string>>(data_lang)143.sortBy((_v, k) => k.toLowerCase());144return [by_name, by_lang];145}146147/*148* select all kernels, which are ranked highest for a specific language.149*150* kernel metadata looks like that151*152* "display_name": ...,153* "argv":, ...154* "language": "sagemath",155* "metadata": {156* "cocalc": {157* "priority": 10,158* "description": "Open-source mathematical software system",159* "url": "https://www.sagemath.org/",160* "disabled": true161* }162* }163*164* Return dict of language <-> kernel_name165*/166export function get_kernel_selection(167kernels: Kernels,168): immutable.Map<string, string> {169// for each language, we pick the top priority kernel170const data: any = {};171kernels172.filter((entry) => entry.get("language") != null)173.groupBy((entry) => entry.get("language"))174.forEach((kernels, lang) => {175const top: any = kernels176.sort((a, b) => {177const va = -(a.getIn(178["metadata", "cocalc", "priority"],1790,180) as number);181const vb = -(b.getIn(182["metadata", "cocalc", "priority"],1830,184) as number);185return cmp(va, vb);186})187.first();188if (top == null || lang == null) return true;189const name = top.get("name");190if (name == null) return true;191data[lang] = name;192});193194return immutable.Map<string, string>(data);195}196197198