###############################################################################1#2# CoCalc: Collaborative Calculation in the Cloud3#4# Copyright (C) 2016, Sagemath Inc.5#6# This program is free software: you can redistribute it and/or modify7# it under the terms of the GNU General Public License as published by8# the Free Software Foundation, either version 3 of the License, or9# (at your option) any later version.10#11# This program is distributed in the hope that it will be useful,12# but WITHOUT ANY WARRANTY; without even the implied warranty of13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the14# GNU General Public License for more details.15#16# You should have received a copy of the GNU General Public License17# along with this program. If not, see <http://www.gnu.org/licenses/>.18#19###############################################################################2021###22Some functions for working with Sage worksheets (sagews files) --23###2425#---------------------------------------------------------------------------------------------------------26# Support for using synchronized docs to represent Sage Worksheets (i.e., live compute documents)27#---------------------------------------------------------------------------------------------------------2829# WARNING: in Codemirror, to avoid issues with parsing I also set the output marker to be a comment character30# by modifying the python mode as follows: if (ch == "#" || ch == "\uFE21") {3132exports.MARKERS =33cell : "\uFE20"34output : "\uFE21"3536exports.FLAGS = FLAGS =37execute : "x" # request that cell be executed38waiting : "w" # request to execute received, but still not running (because of another cell running)39running : "r" # cell currently running40interrupt : "c" # request execution of cell be interrupted41this_session : "s" # if set, cell was executed during the current sage session.42hide_input : "i" # hide input part of cell43hide_output : "o" # hide output part of cell4445exports.ACTION_FLAGS = [FLAGS.execute, FLAGS.running, FLAGS.waiting, FLAGS.interrupt]46exports.ACTION_SESSION_FLAGS = [FLAGS.execute, FLAGS.running, FLAGS.waiting, FLAGS.interrupt, FLAGS.this_session]4748# Return a list of the uuids of files that are displayed in the given document,49# where doc is the string representation of a worksheet.50# At present, this function finds all output messages of the form51# {"file":{"uuid":"806f4f54-96c8-47f0-9af3-74b5d48d0a70",...}}52# but it could do more at some point in the future.5354exports.uuids_of_linked_files = (doc) ->55uuids = []56i = 057while true58i = doc.indexOf(exports.MARKERS.output, i)59if i == -160return uuids61j = doc.indexOf('\n', i)62if j == -163j = doc.length64line = doc.slice(i, j)65for m in line.split(exports.MARKERS.output).slice(1)66# Only bother to run the possibly slow JSON.parse on file messages; since67# this function would block the global hub server, this is important.68if m.slice(0,8) == '{"file":'69mesg = JSON.parse(m)70uuid = mesg.file?.uuid71if uuid?72uuids.push(uuid)73i = j747576class SageWS77constructor: (@content) ->7879find_cell_meta: (id, start) =>80i = @content.indexOf(exports.MARKERS.cell + id, start)81j = @content.indexOf(exports.MARKERS.cell, i+1)82if j == -183return undefined84return {start:i, end:j}8586get_cell_flagstring: (id) =>87pos = @find_cell_meta(id)88if pos?89return @content.slice(pos.start+37, pos.end)9091set_cell_flagstring: (id, flags) =>92pos = @find_cell_meta(id)93if pos?94@content = @content.slice(0, pos.start+37) + flags + @content.slice(pos.end)9596remove_cell_flag: (id, flag) =>97s = @get_cell_flagstring(id)98if s? and flag in s99@content = @set_cell_flagstring(id, s.replace(new RegExp(flag, "g"), ""))100101set_cell_flag: (id, flag) =>102s = @get_cell_flagstring(id)103if s? and flag not in s104@content = @set_cell_flagstring(id, s + flag)105106exports.sagews = (content) ->107return new SageWS(content)108109