Class: EmacsClient

Inherits:
Object
  • Object
show all
Defined in:
lib/rum/barrel/emacs_client.rb

Overview

Ruby implementation of emacs_source/lib-src/emacsclient.c

Constant Summary collapse

SERVER_MSG_SIZE =

defined in server.el on Emacs 24

1024

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeEmacsClient

Unix



91
92
93
94
# File 'lib/rum/barrel/emacs_client.rb', line 91

def initialize
  @server_file = File.join(ENV['HOME'], '.emacs.d', 'server', 'server')
  read_config
end

Instance Attribute Details

#auth_stringObject

Returns the value of attribute auth_string.



61
62
63
# File 'lib/rum/barrel/emacs_client.rb', line 61

def auth_string
  @auth_string
end

#ipObject

Returns the value of attribute ip.



61
62
63
# File 'lib/rum/barrel/emacs_client.rb', line 61

def ip
  @ip
end

#portObject

Returns the value of attribute port.



61
62
63
# File 'lib/rum/barrel/emacs_client.rb', line 61

def port
  @port
end

Instance Method Details

#connectObject



86
87
88
89
# File 'lib/rum/barrel/emacs_client.rb', line 86

def connect
  create_socket or (read_config and create_socket) \
  or raise "Can't connect to Emacs Server."
end

#create_socketObject



76
77
78
79
80
81
82
83
84
# File 'lib/rum/barrel/emacs_client.rb', line 76

def create_socket
  return unless @server_active
  begin
  	socket = TCPSocket.open(@ip, @port)
    socket.write "-auth #@auth_string "
    socket
  rescue SystemCallError
  end
end

#eval(elisp) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/rum/barrel/emacs_client.rb', line 10

def eval(elisp)
  socket = connect
  $socket = socket
  socket.puts "-eval #{quote(elisp)}"

  messages = []
  # On Emacs 24, the first message always has type '-emacs-pid'
  # On Emacs 23, only one message is returned after sending '-eval'.
  # It has type '-print' or '-error' and can be arbitrarily long.
  msg = socket.gets
  loop do
    break if handle_message(msg, messages) == :abort
    msg = socket.recv(SERVER_MSG_SIZE)
  end
  socket.close
  unquote(messages.join)
end

#handle_message(msg, messages) ⇒ Object



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/rum/barrel/emacs_client.rb', line 28

def handle_message(msg, messages)
  return :abort if not msg or msg.empty?

  if (match = msg.match(/(.*?) (.*)/))
    type, body = match.captures
    case type
    when '-print', '-print-nonl'
      messages << body
    when '-error'
      messages << body
      return :abort
    end
  else
    messages << "Error: Unknown message: #{msg}"
    return :abort
  end
end

#quote(str) ⇒ Object



46
47
48
# File 'lib/rum/barrel/emacs_client.rb', line 46

def quote str
  r = str.gsub(/&|^-/, '&\&').gsub("\n", '&n').gsub(' ', '&_')
end

#read_configObject



68
69
70
71
72
73
74
# File 'lib/rum/barrel/emacs_client.rb', line 68

def read_config
  @server_active = File.exists? @server_file
  return unless @server_active
  lines = File.readlines(@server_file)
  @ip, @port = lines.first.match(/(.*?):(\d+)/).captures
  @auth_string = lines.last
end

#unquote(str) ⇒ Object



50
51
52
53
54
55
56
57
58
# File 'lib/rum/barrel/emacs_client.rb', line 50

def unquote str
  str.gsub(/&(.)/) do
    case $1
    when 'n'; "\n"
    when '_'; ' '
    else $1
    end
  end
end