Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/smc_pyutil/smc_pyutil/smc_open.py
Views: 285
1
#!/usr/bin/python
2
3
# Maximum number of files that user can open at once using the open command.
4
# This is here to avoid the user opening 100 files at once (say)
5
# via "open *" and killing their frontend.
6
from __future__ import absolute_import
7
from __future__ import print_function
8
MAX_FILES = 15
9
10
# ROOT_SYMLINK is a symlink to / from somehow in the user's home directory.
11
# This symlink should get created as part of project startup, so that we can
12
# treat all paths in the filesystem as being contained in the user's home direoctory.
13
# This may be dumb but simplifies our code and is assumed in some places.
14
# ~$ ls -ls .smc/root
15
# 0 lrwxrwxrwx 1 user user 1 Oct 22 23:00 .smc/root -> /
16
ROOT_SYMLINK = '.smc/root'
17
18
import json, os, sys
19
20
home = os.environ['HOME']
21
22
if 'TMUX' in os.environ:
23
prefix = '\x1bPtmux;\x1b'
24
postfix = '\x1b\\'
25
else:
26
prefix = ''
27
postfix = ''
28
29
30
def process(paths):
31
v = []
32
if len(paths) > MAX_FILES:
33
sys.stderr.write(
34
"You may open at most %s at once using the open command; truncating list\n"
35
% MAX_FILES)
36
paths = paths[:MAX_FILES]
37
for path in paths:
38
if not path:
39
continue
40
if not os.path.exists(path) and any(c in path for c in '{?*'):
41
# If the path doesn't exist and does contain a shell glob character which didn't get expanded,
42
# then don't try to just create that file. See https://github.com/sagemathinc/cocalc/issues/1019
43
sys.stderr.write("no match for '%s', so not creating\n" % path)
44
continue
45
if not os.path.exists(path):
46
if '/' in path:
47
dir = os.path.dirname(path)
48
if not os.path.exists(dir):
49
sys.stderr.write("creating directory '%s'\n" % dir)
50
os.makedirs(dir)
51
if path[-1] != '/':
52
sys.stderr.write("creating file '%s'\n" % path)
53
from . import new_file
54
new_file.new_file(
55
path
56
) # see https://github.com/sagemathinc/cocalc/issues/1476
57
58
if not path.startswith('/'):
59
# we use pwd instead of getcwd or os.path.abspath since we want this to
60
# work when used inside a directory that is a symlink! I could find
61
# no analogue of pwd directly in Python (getcwd is not it!).
62
path = os.path.join(os.popen('pwd').read().strip(), path)
63
64
# Make name be the path to the file, **relative to home directory**
65
if path.startswith(home):
66
name = path[len(home) + 1:]
67
else:
68
# use the / symlink -- see https://github.com/sagemathinc/cocalc/issues/4188
69
name = ROOT_SYMLINK + path
70
71
# Is it a file or directory?
72
if os.path.isdir(path):
73
v.append({'directory': name})
74
else:
75
v.append({'file': name})
76
77
if v:
78
mesg = {'event': 'open', 'paths': v}
79
ser = json.dumps(mesg, separators=(',', ':'))
80
print(prefix + '\x1b]49;%s\x07' % ser + postfix)
81
82
83
def main():
84
if len(sys.argv) == 1:
85
print("Usage: open [path names] ...")
86
print(
87
"Opens each file (or directory) in the CoCalc web-based editor from the shell."
88
)
89
print("If the named file doesn't exist, it is created.")
90
else:
91
process(sys.argv[1:])
92
93
94
if __name__ == "__main__":
95
main()
96
97