Fork me on GitHub
#cursive
<
2017-04-22
>
onetom04:04:44

@slipset btw, the original meaning of cmd-. is pretty good (folding the top-level-form under the caret) why do u want to use it for going to the declaration? what environment uses cmd-. for that purpose? i've tried all the major editors for editing clojure (except eclipse) and i found learning the cursive keybindings the most economical choice GIVEN i don't work much with any other language

cfleming04:04:06

@onetom That’s Emacs does that

cfleming04:04:59

@onetom - so WRT your question above, that’s a bit tricky. I think the best way to handle this would be to generate your project.clj files from build.boot, and then import those. If you’d like to do it step by step, you can use the IntelliJ option to create an empty project, and then add the modules one by one.

cfleming04:04:20

Actually, I just tried that, and I see what you mean - it doesn’t show the module right away, that does look like an IntelliJ bug.

onetom04:04:36

phew, so it's not just me 🙂

onetom04:04:23

im still not sure what should i do to make the newly added module appear. if i close the project window and re-open it, then it does appear, but sometimes that's not necessary

cfleming04:04:26

Actually, I lie - it’s a Cursive bug.

onetom04:04:40

oh, because it's specific to lein modules?

cfleming04:04:48

It looks like that flow does something different to the usual flow. I’ll fix that on Monday.

cfleming04:04:32

I still think the best option is the single import from the project root directory, searching recursively for project.clj files.

cfleming04:04:49

Because I’ve tested that a lot, and it definitely works.

cfleming04:04:03

Are you generating multiple project.clj files from one build.boot?

onetom04:04:38

understood. i will do so. i think it's just confusing for new projects, so existing cursive users can live with it, but it would be very off-putting for new adopters.

onetom04:04:59

no, every sub-dir has its own build.boot

cfleming04:04:27

Yes, the IntelliJ project setup is intrinsically complicated. It’s very flexible, but it’s hard to make that simple at the same time.

onetom04:04:44

but i was thinking about having a top-level one actually. that would be an interesting approach too

cfleming04:04:09

boot doesn’t really have any multi-module support, right?

onetom04:04:45

im not familiar with lein enough still, so i don't exactly understand what multi-module means. boot does have a checkout built-in task which explodes dependent jars into a boot temp folder (outside of the project dir) and adds it to the sources path set.

cfleming04:04:54

So multi-module basically means one conceptual large project made up of smaller sub-projects, each of which is a lein “project” (or Maven, Gradle, whatever).

cfleming04:04:00

Cursive is like that, for example.

cfleming04:04:24

In IntelliJ’s terminology, Cursive is one project, and the sub-projects are modules.

cfleming04:04:52

Confusingly, lein uses “project” for a single part of that.

cfleming04:04:11

i.e. lein really has an assumption that you’ll only ever have one project.clj, which is not great IMO

onetom04:04:34

in intellij's approach the reason to group modules into projects is because you want to combine them into one artefact at the end? vs simply editing all the source code of a microservices system in one window?

cfleming04:04:06

No, it means that you can easily edit the code of multiple modules in the same project, with cross-module refactoring, navigation etc

cfleming05:04:56

Cursive creates multiple artifacts. They’re later combined into a single one for deployment, but that’s not required.

onetom05:04:09

so you can do such refactoring on keywords for example even if the modules won't end up in the same artefact and the same runtime process?

cfleming05:04:45

I have to go, sorry - let me know how you get on with the multi-module import.

onetom05:04:47

it's really amazing

onetom05:04:57

thanks a lot and have a good day!

cfleming05:04:09

Yes, you can find usages of symbols across the whole project.

cfleming05:04:27

And Cursive actually fixes things up so checkouts are not required for interdependent modules.

cfleming05:04:35

Thanks, you too!

rasom06:04:28

Hi, @cfleming. I know that this is not exactly channel’s topic, but maybe you have a quick answer. I’m trying to create a plugin for intellij using https://github.com/cursive-ide/gradle-clojure, It successfully passes compilation but when I run it with ./gradlew runIde I get:

java.lang.ExceptionInInitializerError
	at clojure.lang.Namespace.<init>(Namespace.java:34)
    at clojure.lang.Namespace.findOrCreate(Namespace.java:176)
    at clojure.lang.Var.internPrivate(Var.java:151)
    at MyClassDefindedInClojure.<clinit>(Unknown Source)
    ...
Caused by: java.io.FileNotFoundException: Could not locate clojure/core__init.class or clojure/core.clj on classpath.
...
So, my dumb question is: should i add clojure to the classpath somewhere inside compileClojure configuration or in some other place to make it work? If so, where exactly? Thanks in advance.

cfleming03:04:13

@U0GB2S42H Sorry for the long delay here, yes, you should add Clojure as a compile dependency. I assume you’re using gradle-intellij-plugin? If so, that will bundle it up into the lib dir of your plugin, and it’ll be available at runtime.

rasom04:04:09

Thank you for answer, Colin. I’ve added it, and you are right, it is bundled into plugin’s lib dir… But nevertheless, I still have this error.

buildscript {
    repositories {
        mavenCentral()
        maven { url '' }
    }
}

plugins {
    id "org.jetbrains.intellij" version "0.2.8"
    id "com.cursive-ide.clojure" version "1.1.0"
}

intellij {
    version '15.0.4'
    pluginName 'rfd'
    updateSinceUntilBuild = false
}

apply plugin: 'org.jetbrains.intellij'

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.clojure', name: 'clojure', version: '1.8.0'
}

compileClojure {
    aotCompile = true
}
That was my last try

rasom04:04:17

When I comment out dependencies i get Error: Could not find or load main class clojure.main at :compileClojure

cfleming07:04:07

Ok, so I think the problem is probably that you have to set the Compiler.LOADER var to your PluginClassLoader.

cfleming07:04:09

Here’s some black magic for that. Put it in an ApplicationComponent called InitComponent:

public void initComponent() {
    initClojure();
    ...
  }

  public static void initClojure() {
    synchronized (LOCK) {
      if (!initialised) {
        ClassLoader loader = InitComponent.class.getClassLoader();

        ClassLoader oldLoader = Thread.currentThread().getContextClassLoader();
        try {
          Thread.currentThread().setContextClassLoader(loader);

          // dummy to force RT class load first, since it has a circular static
          // initializer loop with Compiler
          new RT();

          Compiler.LOADER.bindRoot(loader);

          try {
            RT.var(ClojureUtils.CORE_NAMESPACE, REQUIRE_FUNCTION).invoke(INITIALISE_NS_SYMBOL);
            RT.var(INITIALISE_NS, INITIALISE).invoke();

          } catch (Exception e) {
            logger.error("Error initialising:", e);
          } finally {
            Var.popThreadBindings();
          }

          initialised = true;
        } catch (Exception e) {
          logger.error(e, e);
        } finally {
          Thread.currentThread().setContextClassLoader(oldLoader);
        }
      }
    }
  }

cfleming07:04:53

I actually need to write a blog post about this, since a few people have asked me about it now.

rasom08:04:44

Thank you again, Colin, will try this later. And about blog post, that would be great!

rasom08:04:37

Can you elaborate this?

RT.var(ClojureUtils.CORE_NAMESPACE, REQUIRE_FUNCTION).invoke(INITIALISE_NS_SYMBOL);
RT.var(INITIALISE_NS, INITIALISE).invoke();
I suppose that ClojureUtils.CORE_NAMESPACE = clojure.core REQUIRE_FUNCTION = require INITIALISE = true/false but not sure about INITIALISE_NS_SYMBOL and INITIALISE_NS

rasom09:04:06

ok, i think i figured

RT.var("clojure.core", "require").invoke(Symbol.intern("my.ns"));
RT.var("my.ns", "init_function").invoke();

cfleming10:04:08

That’s right. It’s getting late here, I’ll write more tomorrow.

rasom03:04:03

thank you

cfleming22:04:03

Actually, I’ll try to blog about this in the near future since several people have asked be about this recently.

rasom04:04:33

Will appreciate this, it still doesn’t work on my side. I tried that code but without success. I’m going to make another attempt on weekend and... waiting for blog post 🙂

rasom14:04:33

Just tried again, it works, thank you again, @cfleming