OILS / builtin / method_other.py View on Github | oils.pub

120 lines, 63 significant
1"""Methods on various types"""
2
3from __future__ import print_function
4
5from _devbuild.gen.syntax_asdl import command_e, BraceGroup, command_t
6from _devbuild.gen.value_asdl import (value, value_t, LiteralBlock, cmd_frag,
7 cmd_frag_e)
8
9from core import num
10from core import state
11from core import vm
12from display import ui
13from frontend import typed_args
14from mycpp.mylib import log, tagswitch, NewDict
15
16from typing import Dict, Optional, cast
17
18_ = log
19
20
21class SetValue(vm._Callable):
22
23 def __init__(self, mem):
24 # type: (state.Mem) -> None
25 self.mem = mem
26
27 def Call(self, rd):
28 # type: (typed_args.Reader) -> value_t
29
30 # This is guaranteed
31 place = rd.PosPlace()
32
33 val = rd.PosValue()
34 rd.Done()
35
36 self.mem.SetPlace(place, val, rd.LeftParenToken())
37
38 return value.Null
39
40
41class SourceCode(vm._Callable):
42
43 def __init__(self):
44 # type: () -> None
45 pass
46
47 def Call(self, rd):
48 # type: (typed_args.Reader) -> value_t
49
50 cmd = rd.PosCommand()
51 rd.Done()
52
53 # For now, we only have lines if the block arg is literal like p { echo
54 # hi }
55 # As opposed to
56 # p (; ; myblock)
57
58 lit_block = None # type: Optional[LiteralBlock]
59 frag = cmd.frag
60 with tagswitch(frag) as case:
61 if case(cmd_frag_e.LiteralBlock):
62 lit_block = cast(LiteralBlock, frag)
63 elif case(cmd_frag_e.Expr):
64 c = cast(cmd_frag.Expr, frag).c
65 return value.Null
66 else:
67 raise AssertionError()
68
69 result = NewDict() # type: Dict[str, value_t]
70
71 brace_group = lit_block.brace_group
72 # BraceGroup has location for {
73 line = brace_group.left.line
74
75 # for the user to pass back to --location-str
76 result['location_str'] = value.Str(ui.GetLineSourceString(line))
77 result['location_start_line'] = num.ToBig(line.line_num)
78
79 #log('LINES %s', lit_block.lines)
80 # Between { and }
81 #code_str = alloc.SnipCodeBlock(brace_group.left, brace_group.right,
82 # lit_block.lines)
83
84 result['code_str'] = value.Str(lit_block.code_str)
85
86 return value.Dict(result)
87
88
89def GetDocComment(body):
90 # type: (command_t) -> Optional[str]
91
92 doc = None # type: Optional[str]
93 if body.tag() == command_e.BraceGroup:
94 bgroup = cast(BraceGroup, body)
95 if bgroup.doc_token:
96 token = bgroup.doc_token
97 # 1 to remove leading space
98 doc = token.line.content[token.col + 1:token.col + token.length]
99 return doc
100
101
102class DocComment(vm._Callable):
103
104 def __init__(self):
105 # type: () -> None
106 pass
107
108 def Call(self, rd):
109 # type: (typed_args.Reader) -> value_t
110
111 proc_val = rd.PosProc()
112 rd.Done()
113 # TODO: __invoke__ method could have a doc string too
114
115 doc = GetDocComment(proc_val.body)
116
117 if doc is not None:
118 return value.Str(doc)
119 else:
120 return value.Null