Git Product home page Git Product logo

clomacs's Introduction

License GPL 3 MELPA Melpa Stable Build Status Coverage Status

clomacs

Clomacs logo

Emacs is a Lisp. Clojure is a Lisp. Can the two be put together to form the ultimate dev environment? "Clomacs" perhaps?

  • from Emacs isn't for everyone discussion by Anonymous Cow.

Clomacs simplifies call Clojure code from Emacs lisp and vice versa. The purpose is to provide a tool for creating mixed Elisp-Clojure Emacs extensions. It provides a small wrapper under CIDER to reduce repetitive code and uses simple-httpd to call Elisp from Clojure via http requests.

Overview

There are some requirements to run mixed Elisp-Clojure code. All the Elisp-side code should be loaded, nREPL must run with all related Clojure-side code and its dependencies.

So, the user of the mixed Elisp-Clojure Emacs extension wants to simple run Elisp code from the extension.

The purpose of the clomacs-defun is to wrap Clojure function in a Elisp function, that will start CIDER if necessary or use an existing CIDER connection of certain Elisp-Clojure Emacs extension, call this Clojure function and return it's result.

To run Elisp code from Clojure, http server on Emacs side should be started first by clomacs-httpd-start function. Then you can straightforwardly pass Elisp code as string to Emacs for eval - clomacs-eval or wrap Elisp to Clojure function via clomacs-defn.

Installation

Elisp side

Add MELPA (if not yet) to your package-archives list.

Then you can install clomacs with the following command:

M-x package-install [RET] clomacs [RET]

Clojure side

To install Clomacs, add the following dependency to your project.clj file:

Clojars Project

Usage

Prerequisites

clomacs requires Clojure 1.7+.

Simple example

Call Clojure from Elisp:

;; emacs lisp:
(require 'clomacs)
(clomacs-defun get-property System/getProperty)
(message (get-property "java.version"))

Call Elisp from Clojure:

;; emacs lisp:
(require 'clomacs)
(clomacs-httpd-start)
;; clojure:
(use 'clomacs)
(clomacs-defn emacs-version emacs-version)
(println (emacs-version))

Here System/getProperty is a Clojure function and get-property is a wrapped Elisp function. emacs-version is Elisp function and after macros evaluation - is a wrapped Clojure function.

Full-fledged example

The full source code for the following example is here: cm-test.

1. Create new Clojure project in a common way:

lein new cm-test

2. Add markdown-clj dependency to the project.clj file, add src/clj folder to the classpath:

(defproject cm-test "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :source-paths ["src/clj"]                    ;; add clj folder to the classpath
  :dependencies [[org.clojure/clojure "1.9.0"] ;; Use recent version of Clojure
                 [markdown-clj "0.9.28"]       ;; markdown-clj dependency
                 [clomacs "0.0.3-SNAPSHOT"]])  ;; Most recent version of clomacs

3. Create clj folder in the src/.
4. Copy cm_test to src/clj/ folder.
5. Add some code, using markdown lib in the src/clj/cm_test/core.clj file:

(ns cm-test.core
  (:use markdown.core))

(defn my-md-to-html-string
  "Call some function from the dependency."
  [x]
  (md-to-html-string x))

6. Create elisp folder in the src/.
7. Create cm-test.el file in this foder.
8. Add to the cm-test.el the following content:

(require 'clomacs)
(clomacs-defun cm-test-md-to-html-wrapper
               cm-test.core/my-md-to-html-string
               :lib-name "cm-test"
               :namespace cm-test.core
               :doc "Convert markdown to html via Clojure lib.")

(defun cm-test-mdarkdown-to-html (beg end)
  "Add to the selected markdown text it's html representation."
  (interactive "r")
  (save-excursion
    (if (< (point) (mark))
        (exchange-point-and-mark))
    (insert
     (concat "\n" (cm-test-md-to-html-wrapper
                   (buffer-substring beg end))))))

(provide 'cm-test)

Here is the cm-test/src path tree vizualization:

  • src
    • clj
      • cm_test
        • core.clj
    • elisp
      • cm-test.el

9. So, it can be used in your .emacs via:

(add-to-list 'load-path "~/.emacs.d/cm-test/src/elisp/")
(require 'cm-test)

10. Then mark (select) this text in one of your buffers:
# This is a test
and run M-x cm-test-mdarkdown-to-html.

<h1>This is a test</h1> should occurs in the buffer under the original text.

Projects uses clomacs:

  • cm-test - Clomacs usage example.
  • ejc-sql - Emacs SQL client uses Clojure JDBC.
  • flower - Integration with Github, Gitlab, Atlassian Jira, Microsoft TFS, Microsoft Exchange and Slack.

Requirements:

License

Copyright © 2013-2023 Kostafey [email protected] and contributors

Distributed under the General Public License, version 3.

clomacs's People

Contributors

agilecreativity avatar bbatsov avatar danielcompton avatar davidpham87 avatar ebpa avatar kostafey avatar profitware avatar syohex avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

clomacs's Issues

Passing escaped substrings

Great tool. Makes a nice bridge.

I ran into one issue so far though where if the string you are passing through has substrings. These get processed by the clojure reader and break compilation.

For example- the clomacs demo will break if the selection you highlight is:

This is "a" test

instead of

This is a test

or if you call (cm-test-md-to-html-wrapper "# This is "a" test")

Clojure will throw a runtime exception complaining that it cannot resolve the symbol: a in this context. because the request passed to the repl will actually be "This is "a" test" (inner quotes not escaped).

Workaround:
in clomacs.el in the method: clomacs-add-quotes I replaced
(concat """ str """)
with
(format "%S" str)

With the capital S directive it still generates the string representation but uses prin1 for the formatting which attempts to escape things so that read will reproduce the string properly.

This seems to work for my testing so far (I haven't played with super nested substrings) but I'm not sure if there's some other reason the system manually created the string the original way (new to this entire framework).

Versions:
Windows: Windows 10 Pro Version: 1703 Build: 15063.413
Emacs: GNU Emacs 25.2.1 (x86_64-w64-mingw32) of 2017-04-24
Clomacs: installed from MELPA
Clojure: 1.8.0

void variable clomacs--doc

every time when I eval (require 'clomacs) it shows
Debugger entered--Lisp error: (void-variable clomacs--doc)

Emacs version:24.5
OS:windows 10(does this matter?)

Create clomacs server

Create clomacs server to operate with different mixed Elisp-Clojure Emacs extensions from one nREPL.

Error: Symbol’s function definition is void: clomacs-doc

When I tried to install clomacs using mepla. I got this error message.

clomacs.el:339:1:Error: Symbol’s function definition is void: clomacs-doc

I cloned this clomacs repo, and revert back to this commit: 6d4eb7a . I can load the lisp
clomacs.el. Because some one here kostafey/ejc-sql#11 (comment) indicted that he install successfully that time.

Because I don't have too much knowledge about clojure. I can't really send a pull request.
Can you verify this?

Try README CLJ call Elisp function demo error

When I try the README Clojure call Elisp function demo, I got error:

Call Elisp from Clojure:

;; emacs lisp:
(require 'clomacs)
(clomacs-httpd-start)
;; clojure:
(use 'clomacs)
(clomacs-defn emacs-version emacs-version)
(println (emacs-version))
2. Unhandled java.lang.ExceptionInInitializerError
   (No message)

5173d5e1d3884202be02833334f1f23375658f5d-init.clj:    1  user/eval10423/emacs-version
               RestFn.java:  397  clojure.lang.RestFn/invoke
5173d5e1d3884202be02833334f1f23375658f5d-init.clj:    4  user/eval10435
5173d5e1d3884202be02833334f1f23375658f5d-init.clj:    1  user/eval10435
             Compiler.java: 7062  clojure.lang.Compiler/eval
             Compiler.java: 7025  clojure.lang.Compiler/eval
                  core.clj: 3206  clojure.core/eval
                  core.clj: 3202  clojure.core/eval
             enlighten.clj:   84  cider.nrepl.middleware.enlighten/eval-with-enlighten
             enlighten.clj:   78  cider.nrepl.middleware.enlighten/eval-with-enlighten
                  Var.java:  381  clojure.lang.Var/invoke
    interruptible_eval.clj:   91  nrepl.middleware.interruptible-eval/evaluate/fn
                  main.clj:  243  clojure.main/repl/read-eval-print/fn
                  main.clj:  243  clojure.main/repl/read-eval-print
                  main.clj:  261  clojure.main/repl/fn
                  main.clj:  261  clojure.main/repl
                  main.clj:  177  clojure.main/repl
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   84  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   56  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  153  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
                  AFn.java:   22  clojure.lang.AFn/run
               session.clj:  190  nrepl.middleware.session/session-exec/main-loop/fn
               session.clj:  189  nrepl.middleware.session/session-exec/main-loop
                  AFn.java:   22  clojure.lang.AFn/run
               Thread.java:  834  java.lang.Thread/run

1. Caused by java.lang.IllegalArgumentException
   No matching ctor found for class clojure.lang.AFunction$1

            Reflector.java:  163  clojure.lang.Reflector/invokeConstructor
           LispReader.java: 1303  clojure.lang.LispReader$EvalReader/invoke
           LispReader.java:  843  clojure.lang.LispReader$DispatchReader/invoke
           LispReader.java:  275  clojure.lang.LispReader/read
           LispReader.java:  206  clojure.lang.LispReader/read
           LispReader.java:  195  clojure.lang.LispReader/read
                   RT.java: 1871  clojure.lang.RT/readString
                   RT.java: 1866  clojure.lang.RT/readString
5173d5e1d3884202be02833334f1f23375658f5d-init.clj:    1  user/eval10423/emacs-version/fn
5173d5e1d3884202be02833334f1f23375658f5d-init.clj:    1  user/eval10423/emacs-version
               RestFn.java:  397  clojure.lang.RestFn/invoke
5173d5e1d3884202be02833334f1f23375658f5d-init.clj:    4  user/eval10435
5173d5e1d3884202be02833334f1f23375658f5d-init.clj:    1  user/eval10435
             Compiler.java: 7062  clojure.lang.Compiler/eval
             Compiler.java: 7025  clojure.lang.Compiler/eval
                  core.clj: 3206  clojure.core/eval
                  core.clj: 3202  clojure.core/eval
             enlighten.clj:   84  cider.nrepl.middleware.enlighten/eval-with-enlighten
             enlighten.clj:   78  cider.nrepl.middleware.enlighten/eval-with-enlighten
                  Var.java:  381  clojure.lang.Var/invoke
    interruptible_eval.clj:   91  nrepl.middleware.interruptible-eval/evaluate/fn
                  main.clj:  243  clojure.main/repl/read-eval-print/fn
                  main.clj:  243  clojure.main/repl/read-eval-print
                  main.clj:  261  clojure.main/repl/fn
                  main.clj:  261  clojure.main/repl
                  main.clj:  177  clojure.main/repl
               RestFn.java: 1523  clojure.lang.RestFn/invoke
    interruptible_eval.clj:   84  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:   56  nrepl.middleware.interruptible-eval/evaluate
    interruptible_eval.clj:  153  nrepl.middleware.interruptible-eval/interruptible-eval/fn/fn
                  AFn.java:   22  clojure.lang.AFn/run
               session.clj:  190  nrepl.middleware.session/session-exec/main-loop/fn
               session.clj:  189  nrepl.middleware.session/session-exec/main-loop
                  AFn.java:   22  clojure.lang.AFn/run
               Thread.java:  834  java.lang.Thread/run

Passing map to clojure via alist

Is this alist handling behavior expected? I don't know if there are some limitations here but it doesn't seem to recognize all elisp alists.

(json-alist-p '((1 2))) => t
(clomacs-alist-p '((1 2))) => nil
(clomacs-alist-to-map '((1 2))) => "{1 '(2)}"

In particular I'm trying to pass a map from elisp to clojure, and I'm not sure how to specify that other than an alist.

nrepl not found

First of all,
THANK YOU.
This integration is exactly I was looking for. Great job. Keep up the good work :-)

I had the problem that the nrepl was started correctly but was not found by "clomacs" ("NO repl buffer found - error").

It turned out that the nrepl-connection-list is correctly filled. So the only thing I had to do was to prevent clomacs-defun (line 259) to set the nrepl-connection-list anew.

The setup I use is:
emacs 24.4
mac os x 10.8
cider 20150604.1532
cider-nrepl [cider/cider-nrepl "0.9.0-SNAPSHOT"]
nrepl [org.clojure/tools.nrepl "0.2.10"];; actually 0.2.6 is loaded by lein, but that's a different story
java 1.8.0_40

Async call-type example

Hello,

Thanks a lot for the library, I recently took time and I managed to make it work with babashka (it is quite easy as babashka has an integrated nrepl-server), you just need to make a process and connect to it with cider.

I was trying to look for example of clomacs-defun with an async function, and I wonder if you had any example of callback function? I triend the identity, but it does not work.

Best regards,
David

clomacs-httpd-start FileNotFoundException on Windows 10

Hi,

I'm having troubles starting http server using (clomacs-httpd-start):

Debugger entered--Lisp error: (error "FileNotFoundException Could not locate clomacs__init.class or clomacs.clj on classpath.  clojure.lang.RT.load (RT.java:456)
")
  signal(error ("FileNotFoundException Could not locate clomacs__init.class or clomacs.clj on classpath.  clojure.lang.RT.load (RT.java:456)\n"))
  error("FileNotFoundException Could not locate clomacs__init.class or clomacs.clj on classpath.  clojure.lang.RT.load (RT.java:456)\n")
  clomacs-get-result((dict "status" ("eval-error" "done" "state") "ex" "class java.io.FileNotFoundException" "id" "11" "root-ex" "class java.io.FileNotFoundException" "session" "5933c6ef-b53c-4e22-9264-87d6a3825e1a" "err" "FileNotFoundException Could not locate clomacs__init.class or clomacs.clj on classpath.  clojure.lang.RT.load (RT.java:456)\n" "changed-namespaces" (dict) "repl-type" "clj") :value :string nil)
  clomacs-require((quote clomacs))
  clomacs-httpd-start()
  eval((clomacs-httpd-start) nil)
  elisp--eval-last-sexp(nil)

I'm doing some Clojure with clomacs and it's working fine (I'm able to call Clojure functions from Elisp), but I wanted to use callbacks from Clojure to Emacs and have this issue.

I have Windows 10, Java 1.8, Emacs 25.3.1, Spacemacs.

If you need more information please let me know.

Thanks!
Kirill

Please make cljs-clomacs.

Thanks E.T. uncle.

when

(require 'clomacs)
(clomacs-launch-nrepl nil t) ;; <--- cider-jack-in-cljs options~* :)

Thanks :)) E.T. uncle good day!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.