Skip to content
Laurent Petit edited this page Mar 20, 2015 · 1 revision

Introduction

This page contains Laurent's personal non categorized / non organized thoughts on current and future work.

Details

Refactoring

Adding refactoring ? Here is what Rich thought about it in the ml : The number one refactoring is rename. As Chas said, the Clojure editing environments don't currently support it, but I think Clojure is well-positioned for rename refactoring, especially when compared to Python and Ruby. There, given a rename refactoring of Foo.bar to Foo.baz, it can be very difficult to determine statically whether some call of the form x.bar should be renamed, since the type of x is often unknown.

By contrast, a rename refactoring of foo/bar to foo/baz in Clojure should be straightforward, since every use of bar can be resolved statically to either a local name or a name in a specific namespace. Thus, only those bars that resolve to foo/bar will be renamed.

In short, namespaces make for better namespaces than do classes in dynamically typed languages.

I look forward to good rename refactoring for Clojure. It could even (preferably?) be implemented a la carte, as an independent process invokable by all tools

editor functionality approaching emac's one

from mac on the ml: I use eclipse daily at work so I'm pretty used to it, would be very nice with a clojure plugin. Are you taking feature requests? If you are, here is mine:

I like a good IDE as much as anyone but so far I have been using emacs with Jeffrey Chu's clojure-mode (http://clojure.codestuffs.com/). Coming from a VS/eclipse background I feel comfortable with a full IDE but I have discovered something about most IDE's when I have been using emacs. While they do a good job of integrating stuff, their editors actually suck, at least in their default configurations.

So I humbly submit a request to you to try to make the editor have the same features as the clojure paredit mode, at least as an option one can enable. What I really like about it is that it is sexp-aware, it will help you balance parens and brackets by inserting pairs automatically and prevent you from deleting non empty expressions. There are also keyboard commands for "expanding" or "shrinking" an expression to include/exclude symbols or expressions around it/inside it while automatically preserving correct indentation. Plus of course the standard stuff like keyboard commands for eval last expr, eval buffer, eval region (selection) etc. that really helps with interactive development.

As much as I like the whole IDE idea, I am starting to get so used to the fantastic editor that emacs is when properly configured that I get a little annoyed writing java in eclipse at work because it doesn't really offer much more than syntax highlightning and inserting some brackets (yes code completion is great and all but not really an editor feature in the sense I mean here).

To sum up a very wordy post: if you could make the editor as good as the emacs mode, that would be awesome!

Debugger support in eclipse

"I have added an Eclipse plugin to the files of this group. It allow to put breakpoints on .clj files opened with the default editor. "

C. Grand did this, as posted here in the ml : http://groups.google.com/group/clojure/browse_thread/thread/be21f781cfa46f3/540aba14fe85ea21?lnk=gst&q=editor#540aba14fe85ea21

(some) emacs lisp-mode commands

from (gnu emacs manual) : http://www.delorie.com/gnu/docs/emacs/emacs_268.html

Moving by Defuns http://www.delorie.com/gnu/docs/emacs/emacs_272.html

  • C-M-a (done)(+ Ctrl+Shift+A) (C-M is Ctrl+Alt - or Altr Gr on windows)
    • Move to beginning of current or preceding defun (beginning-of-defun).
  • C-M-e (+ Ctrl+Shift+E) (done)
    • Move to end of current or following defun (end-of-defun).
  • C-M-h (done)
    • Put region around whole current or following defun (mark-defun).

Indentation for programs http://www.delorie.com/gnu/docs/emacs/emacs_275.html

Commands for Editing with Parentheses http://www.delorie.com/gnu/docs/emacs/emacs_281.html

Manipulating Comments http://www.delorie.com/gnu/docs/emacs/emacs_285.html

Slime-mode commands summary

(comes from http://common-lisp.net/project/slime/doc/slime.pdf ) This can be a good source to list the functionalities the editor might have.

If some key bindings do not exist yet in eclipse, it could be good to be compatible with slime in these areas. Furthermore, it could be interesting to eventually investigate in eclipse emacs mode to see how to plug into it, and maybe add to it the commands that are below, too.

  • C-c C-k slime-compile-and-load-file

    • Compile and load the current buffer’s source file.
  • C-c M-k slime-compile-file

    • Compile (but don’t load) the current buffer’s source file.
  • C-c C-c slime-compile-defun

    • Compile the top-level form at point.
  • M-p slime-next-note, slime-previous-note

    • These commands move the point between compiler notes and display the new note.
  • C-c M-c slime-remove-notes

    • Remove all annotations from the buffer.

Finding definitions The familiar M-. command is provided. For generic functions this command finds all methods, and with some systems it does other fancy things (like tracing structure accessors to their DEFSTRUCT definition).

  • M-. slime-edit-definition
    • Go to the definition of the symbol at point.
  • M-, slime-pop-find-definition-stack Go back from a definition found with M-..
    • This gives multi-level backtracking when M-. has been used several times.

Lisp Evaluation These commands each evaluate a Lisp expression in a different way. By default they show their results in a message, but a prefix argument causes the results to be printed in the repl instead.

  • C-M-x slime-eval-defun (done)
    • Evaluate top-level form.
  • C-x C-e slime-eval-last-expression
    • Evaluate the expression before point.
  • C-c C-p slime-pprint-eval-last-expression
    • Evaluate the expression before point and pretty-print the result.
  • C-c C-r slime-eval-region (done)
    • Evaluate the region.
  • C-c : slime-interactive-eval
    • Evaluate an expression read from the minibuffer.
  • M-x slime-scratch
    • Create a ‘slime-scratch’ buffer. In this buffer you can enter Lisp expressions and evaluate them with C-j, like in Emacs’s ‘scratch’ buffer. If ‘C-M-x’ or ‘C-x C-e’ is given a numeric argument, it inserts the value into the current buffer at point, rather than displaying it in the echo area.

...

fix import assistant

from the ml (http://groups.google.com/group/clojure/browse_thread/thread/5595e9597e14c8b3?hl=en ) "I've done a bit of Java programming, and one of the reasons I use an IDE (netbeans) rather than plain vim is that I can write code without having to bother about where every class I use comes from, then click 'fix imports' and have netbeans statically examine the code and add import statements. I've missed this in clojure - is it possible in theory to examine a clojure program and a classpath, and generate the import statements needed to make it compile? It needn't do a perfect job, of course, but just handling the common case would be very useful

  • as it is, I have to constantly go looking up the java docs to find out what package provides every class I use. "

personal todo list (unsorted, unprioritized list)

  • DOCUMENT THE LAST CHANGES BEFORE I HAVE FORGOTTEN IMPORTANT DETAIL ! ! !
  • enhance the code completion with the ideas of kotarak (omni completion on clojure, CamelCase completion on java, completion on java class names)
  • update clojuredev website with last enhancements (code completion, preferences, ...)
  • better default syntax coloring (a must if a preference page too)
  • enhance the editor to more correctly handle problems of mixing parens and square brackets ... -> we should show if they are incorrectly intertwinned
  • namespace browser: add a button to show/hide private members
  • see how Tom Faulhaber's pretty printing stuff could benefit to clojuredev, and in which areas (macro expansion -yet to be implemented- ? full file formatting ?).
  • verify that the behaviour of some eval actions work as their slime's equivalents (e.g. is the evaluation done towards the namespace of the edited file, or the namespace currently visible in the REPL. For this particular one, I vote for changing the behavior by sending evaluation towards the namespace of the edited file)
  • add the equivalent of slime's action that allows users to quickly change the REPL's namespace to the editor's one
  • add the equivalent of (slime ?) enclojure action that allows easy switching back and forth between the last opened editor and the repl, and vice versa
  • cleanup the existing actions, and create contextual menus for at least the editor with all the available clojure-related commands (the specific ones, -as well as those that are interesting ?-)
  • repl configuration : add warn-on-reflection, and also use this possibility (with an associated global preference) during the compilation step for generating appropriate warnings
  • create a global preference for auto-switch of the REPL to the ns of the edited file
  • add an option to the repl launch configuration for automatically loading all the files of the project (without having to manually specify those files). This could be implemented as a checkbox, and when checked, the list for manually choosing files would then become non editable
  • change the default behaviour of the launchConfigurationShortcut newly used on project's root to load all files
  • repl : make the cursor go to the end of the console content (not easy, maybe reconsider it when we have a proper REPL - maybe inspired by CUSP's one)
  • repl : add code completion for both clojure and java stuff (idem above)

Enhanced version of code completion

TODO:

  • indicate how the results are displayed in the list of matching candidates
  • indicate for each kind of completion what string will participate to the sorting of the list (if possible at all to sort the list before rendering it)
  • If performance is a problem, consider that versions of completion with / require exact matches before the / (either namespace/alias, either (fully qualified)class name).

Here are my thoughts. I'll write the new version when I have my thoughts clear.

(Global enclojure code completion page: http://www.enclojure.org/Code+Completion )

The following good ideas could be ported to clojuredev:

Different schemes :

.someFunc / .sF + (Ctrl+space)

Searches methods or fields beginning with someFunc or for which sF is the start of camelCased form.

Limits the scope to only methods or fields of the classes imported as symbols in the current namespace. Do not match static methods or fields, only instance methods or fields.

Will result in text insertion such as .someFunction

Needs a running REPL to work (in a future version, we could parse the names of classes from the textual (ns) call, though).

.someFunc / .sF + (Ctrl+space+space)

Same as above, but the scope is not limited to methods or fields of the classes declared in the current namespace : all instance methods or fields of all classes in the classpath will be searched.

Will result in text insertion such as .someFunction.

someFunc / s-f / sF + (Ctrl+space)

Will try to match namespace symbol, java package name, clojure symbol, or java class name.

  • namespace symbol
    • will try to match a namespace using any form, or an alias of a namespace in the current namespace
    • will result in text insertion such as some.matched.namespace
  • java package name
    • will try to match using first or third form (will not try if an hyphen is present). camelCase will be tried.
    • will result in text insertion such as some.matched.package
  • clojure symbol
    • will try to match clojure symbol using one of the 3 forms, with and without omni-completion via hyphen.
  • java class name
    • will try to match with first and third form, trying with camel case.
    • will result in text insertion such as MatchedClassName (if clojuredev knows that MatchedClassName is imported in the current namespace) or full.package.of.MatchedClassName if either clojuredev does not know if MatchedClassName is imported in the current namespace, or if clojuredev knows MatchedClassname is not imported in the current namespace.

Will try to match namespace symbol, java package name or java class name or java instance method call or field. clojure symbol is out of scope since there is a . but no /

  • namespace symbol
    • same as above
  • java package name
    • same as above
  • java class name
    • will consider that everything before the last . is a prefixed possibly camelCased version of a package, and everything after the last . is a prefixed possibly camelCased version of a class name
    • not limited (?) in scope to the classes imported in the current namespace
    • will result in text insertion such as full.package.name.MatchedClassName if clojuredev cannot determine if MatchedClassName is imported in the current namespace, or MatchedClassName if clojuredev can determine that it is imported in the current namespace
  • java instance method call or field
    • will consider that everything before the last . is a prefixed possibly camelCased version of a package+class name, and everything after the last . is a prefixed possibly camelCased version of a method or field
    • will just match instance methods or fields, not class methods
    • will not (?) be limited in scope to the classes imported in the current namespace
    • will result in text insertion such as .matchedMethodName . Will not import the corresponding class to the current namespace

Will try to match clojure symbol or java static method call or field.

  • clojure symbol
    • will consider that everything before the / is a prefixed, possibly omni-completable version of a namespace name or an alias of a namespace in the current namespace , and that everything after the / is a prefixed, possibly omni-completable version of a symbol in that namespace
    • will result in text insertion such as some-function or alias/some-function (if clojuredev can determine that the symbol of the function is mapped in the current namespace), or real.namespace/some-function if clojuredev cannot guess anything
  • java static method call or field
    • will consider that everything before the / is a prefixed, possibly camelCased version of a classname or fullyQualified classname, and that everything after the / is a prefixed, possibly camelCased version of a static method or field
    • will result in text insertion such as ClassName/theMethod if clojuredev can determine that ClassName has a corresponding symbol in the current namespace, or full.package.ClassName/theMethod if clojuredev cannot guess anything.

Notes

  • camelCase notation will work for searching java names

  • omni-completion via . or - will work for searching clojure names

  • all searches will be tried and reported in the same list.

  • matches of java names will be repoerted as italic (same convention as in the source files)

Mac reserved keywords

(from an email from Konrad Hinsen)

Here is what is considered "reserved" on the Mac for all applications:

  • Command-H: hide the windows of the current application
  • Command-Alt-H: hide the windows of all applications other than the current one
  • Command-M: minimize the current window
  • Command-Q: Quit
  • Command-,: Preferences

Moreover, a couple of shortcuts should have the standard meanings if appropriate for the applications:

  • Command-A: Select all
  • Command-X, C, V: cut, copy, paste
  • Command-P: Print
  • Command-N: New
  • Command-O: Open
  • Command-W: Close
  • Command-S: Save
  • Command-Z: Undo

Eclipse uses all of them, but I guess they are the same on the other platforms as well.

The only reserved shortcut with a modifier key in addition to Command is Command-Alt-H, so this was really bad luck.

How would one create a clojure lint ?

from: http://stackoverflow.com/questions/1938242/how-would-one-create-a-clojure-lint

  • One example of a common Clojure programming error is expecting a lazy expression to be evaluated for side-effects. On the surface it appears checking for unused lazy expressions would be helpful. What would be the best approach to identifying this and other common mistakes? Should the core compiler check for these situations, or should it be the domain of a lint program to detect? What would be a good way to start the implementation?
  • Multimethods with no :default method
  • Missing documentation strings
  • In cases where the argument to a function is always the same type, suggesting type hints on arguments
  • Pointing out multiple copies of identical anonymous functions
  • Pointing out tail recursion and suggesting restructuring
  • Using a macro where a function would suffice
  • Unused arguments, especially & rest type arguments
  • Where a function will use BigNums instead of just ints or floating point
  • it could detect lazy code that can never be realized,
  • or point out areas where reflection will be used.

Future releases notes text

  1. Format file * via Ctrl+Shift+F * be aware that it will always format the whole file, not just the selection