Class: Relisp::Slave
- Defined in:
- lib/relisp/slaves.rb,
lib/relisp/elisp_functions.rb
Overview
This is the base class for RubySlave and ElispSlave–the Slave class isn’t meant to be used itself.
Direct Known Subclasses
Constant Summary collapse
- CONSTANTS =
Ruby and elisp use these strings to terminate messages sent to each other. This ruby library and the elisp code are tied to one another so closely that I don’t know if it matters, but it still seemed like a bad idea to hard code the constants in both places. Just make sure that the order in the elisp function
relisp-get-constantsmatches the ruby methodsend_constants. Array.new
- TRANSMISSION_CODES_REGEXP =
Regexp.new(CONSTANTS.join('|'))
- PREVIOUS_ELISP_RESULT =
Every time ruby asks elisp to evaluate an expression, the result is saved in this variable so ruby can access it if necessary.
:"--relisp--previous--result"- VARIABLE_PREFIX =
A prefix for elisp variables created by ruby.
'--relisp--variable--'
Instance Method Summary collapse
-
#elisp_eval(code) ⇒ Object
Run code in the elisp process and return the result as the corresponding ruby object.
-
#elisp_exec(code) ⇒ Object
Run code in the elisp process.
-
#get_permanent_variable(old_variable) ⇒ Object
Return a symbol corresponding to a new elisp variable which hold the same information as old_variable.
-
#initialize ⇒ Slave
constructor
A new instance of Slave.
-
#new_elisp_variable ⇒ Object
Return a symbol which corresponds to an unused variable in elisp.
-
#provide(symbol, binding) ⇒ Object
Creates a method in the slave that is a reference to the variable given by symbol in the scope of binding.
-
#save_excursion ⇒ Object
Save point, mark, and current buffer; execute a block of code; restore those things.
-
#with_current_buffer ⇒ Object
Save the current buffer; execute a block of code; restore the current buffer.
-
#with_temp_buffer ⇒ Object
Create a temporary buffer, and evaluate a block of code there.
Constructor Details
#initialize ⇒ Slave
Returns a new instance of Slave.
65 66 67 68 69 70 71 72 73 74 |
# File 'lib/relisp/slaves.rb', line 65 def initialize # Whenever ruby calls 'eval' on some code at the request of # elisp it is in a context where any new variables set will drop # out of scope immediately. The @local_binding is a way of # allowing these variables to persist through multiple calls. @local_binding = nil @current_elisp_variable_num = '0' @debug = nil Relisp.default_slave = self end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(function, *args) ⇒ Object (private)
Forward any missing method to elisp, writing the function and arguments in prefix notation (calling the to_elisp method of each of the args).
This automatically allows access to a large portion of elisp functions a rubyish way.
93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/relisp/elisp_functions.rb', line 93 def method_missing(function, *args) # :doc: function = function.to_s.gsub('_', '-') unless elisp_eval("(functionp '#{function})") raise NameError, "#{function} is not an elisp function" end elisp_eval('(' + function + ' ' + args.map{|a| a.to_elisp}.join(' ') + ')') end |
Instance Method Details
#elisp_eval(code) ⇒ Object
Run code in the elisp process and return the result as the corresponding ruby object. If the ruby object is not going to be used, use elisp_exec instead.
106 107 108 109 110 111 |
# File 'lib/relisp/slaves.rb', line 106 def elisp_eval(code) code = code.to_s # maybe code is a symbol or something write_to_emacs code write_to_emacs QUESTION_CODE to_ruby(receive_answer) end |
#elisp_exec(code) ⇒ Object
Run code in the elisp process.
95 96 97 98 99 100 |
# File 'lib/relisp/slaves.rb', line 95 def elisp_exec(code) code = code.to_s # maybe code is a symbol or something write_to_emacs code write_to_emacs COMMAND_CODE receive_answer end |
#get_permanent_variable(old_variable) ⇒ Object
Return a symbol corresponding to a new elisp variable which hold the same information as old_variable. Intended primarily for use in the from_elisp method in various classes.
87 88 89 90 91 |
# File 'lib/relisp/slaves.rb', line 87 def get_permanent_variable(old_variable) permanent_variable = new_elisp_variable elisp_exec( "(setq #{permanent_variable} #{old_variable})" ) return permanent_variable end |
#new_elisp_variable ⇒ Object
Return a symbol which corresponds to an unused variable in elisp.
79 80 81 |
# File 'lib/relisp/slaves.rb', line 79 def new_elisp_variable (VARIABLE_PREFIX + @current_elisp_variable_num.succ!).to_sym end |
#provide(symbol, binding) ⇒ Object
Creates a method in the slave that is a reference to the variable given by symbol in the scope of binding. This is probably only useful when calling elisp in ruby where the elisp code itself calls ruby again. When the elisp process calls ruby_eval the code is executed inside the loop of the slave object, so the variables in the scope of the original call to elisp aren’t normally available.
emacs = Relisp::ElispSlave.new
number = 5
emacs.elisp_eval('(ruby-eval "number")') # => [error]
emacs = Relisp::ElispSlave.new
number = 5
local_binding = binding
emacs.provide(:number, local_binding)
emacs.elisp_eval('(ruby-eval "number")') # => 5
216 217 218 219 220 221 222 223 224 |
# File 'lib/relisp/slaves.rb', line 216 def provide(symbol, binding) eval "@__#{symbol.to_s}__binding = binding" instance_eval <<-endstr def #{symbol.to_s} eval("#{symbol.to_s}", @__#{symbol.to_s}__binding) end endstr end |
#save_excursion ⇒ Object
Save point, mark, and current buffer; execute a block of code; restore those things.
This does not simply call the save-excursion function in elisp, it is a rewrite to accept a ruby block.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
# File 'lib/relisp/elisp_functions.rb', line 32 def save_excursion raise ArgumentError unless block_given? begin start_point = point() start_mark = mark() start_buffer = current_buffer() start_active = elisp_eval( "mark-active" ) yield ensure set_buffer(start_buffer) set(:"mark-active", start_active) goto_char(start_point) set_mark(start_mark) end end |
#with_current_buffer ⇒ Object
Save the current buffer; execute a block of code; restore the current buffer.
This does not simply call the with-current-buffer function in elisp, it is a rewrite to accept a ruby block.
54 55 56 57 58 59 60 61 62 |
# File 'lib/relisp/elisp_functions.rb', line 54 def with_current_buffer raise ArgumentError unless block_given? begin start_buffer = current_buffer() yield ensure set_buffer(start_buffer) end end |
#with_temp_buffer ⇒ Object
Create a temporary buffer, and evaluate a block of code there.
This does not simply call the with-temp-buffer function in elisp, it is a rewrite to accept a ruby block.
69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/relisp/elisp_functions.rb', line 69 def with_temp_buffer raise ArgumentError unless block_given? begin start_buffer = current_buffer() temp_buffer = Relisp::Buffer.new("*temp--relisp--buffer*", self) yield ensure set_buffer(start_buffer) temp_buffer.kill end end |