Hi!
I still don't know what is the official way to edit component being compiled. I asked at comp.lang.lisp but had no reply.
But I have developed my own solution. For this I had to redefine several asdf functions. I bind special variables so that current component is known at the time of compilation. Also I define asdf::e and asdf::ep symbol macros that access special variables.
When compilation fails, I have an EDIT-COMPONENT restart, which is not needed - it is just a help string. Then user should eval asdf::e in the debugger to edit component source. User should eval asdf::ep in the debugger to edit component's system source.
Code is here, it shoud work in asdf-3.1.4 under lispworks 6 or under SBCL+SLIME.
https://bitbucket.org/budden/budden-tools/src/866bcf15ad5c793868a0a31e602474...
I'd like to receive any feedback.
On 7/8/15 Jul 8 -6:33 AM, 73budden . wrote:
Hi!
I still don't know what is the official way to edit component being compiled. I asked at comp.lang.lisp but had no reply.
I'm not sure I understand. It looks like what you are building is an extension to ASDF that hooks it into an editor (perhaps specifically the lispworks IDE?). Is that correct?
I have always found the component through ASDF error messages and then opened it by hand. It would probably be nice for whatever IDE one uses (Lispworks, CCL, ACL, SLIME, etc.) to know enough about ASDF to automate this process.
But I have developed my own solution. For this I had to redefine several asdf functions. I bind special variables so that current component is known at the time of compilation. Also I define asdf::e and asdf::ep symbol macros that access special variables.
When compilation fails, I have an EDIT-COMPONENT restart, which is not needed - it is just a help string. Then user should eval asdf::e in the debugger to edit component source. User should eval asdf::ep in the debugger to edit component's system source.
Code is here, it shoud work in asdf-3.1.4 under lispworks 6 or under SBCL+SLIME.
https://bitbucket.org/budden/budden-tools/src/866bcf15ad5c793868a0a31e602474...
I'd like to receive any feedback.
That code is not very readable in its present form. The content of the file is obscured by lots of lines of dead code. How about you clean it up a bit, and comment it a little before soliciting feedback again?
Also, you might want to split this into modifications/extensions to ASDF and code that interfaces to the Lispworks IDE. For questions about the latter, lispworks-hug is probably a more appropriate source of information.
On Wed, Jul 8, 2015 at 10:17 AM, Robert Goldman rpgoldman@sift.net wrote:
Also I define asdf::e and asdf::ep symbol macros that access special variables.
When compilation fails, I have an EDIT-COMPONENT restart, which is not needed - it is just a help string. Then user should eval asdf::e in the debugger to edit component source. User should eval asdf::ep in the debugger to edit component's system source.
Code is here, it shoud work in asdf-3.1.4 under lispworks 6 or under SBCL+SLIME.
https://bitbucket.org/budden/budden-tools/src/866bcf15ad5c793868a0a31e602474...
I'd like to receive any feedback.
That code is not very readable in its present form. The content of the file is obscured by lots of lines of dead code. How about you clean it up a bit, and comment it a little before soliciting feedback again?
Also, you might want to split this into modifications/extensions to ASDF and code that interfaces to the Lispworks IDE. For questions about the latter, lispworks-hug is probably a more appropriate source of information.
The code is overall bad qualify and should be rewritten.
* It has a lot of dead code that should just be removed (if you ever need it again, the version control remembers; have a descriptive message of any interesting bits in your version log).
* It was obviously written for ASDF 1, and tries to do that ASDF 3 does better: see component-find-path, find-component, component-system, load-system, safe-read-from-string and/or eval-input, component-pathname, system-source-file.
* It is very poor taste to use special variables and redefine functions to access the current component. As Robert points out, the correct thing to do is unwrap the component from the error condition that is being handled. This is not C, this is Lisp! (insert this is Sparta meme). Instead of modifying a function to add a restart that doesn't even do the editing for you when it could, why don't you define a handler that adds a restart and re-signals? If somehow this is not possible, it might make sense to add a restart to ASDF itself, which would actually call the editor instead of hint at it, and where the editor, not the component, is the special variable that the user can thereby customize.
* Do NOT use keywordize and string-equal, use coerce-name and string=. You're introducing subtle incompatibility in your semantics.
* run-shell-command is deprecated, it's a braindead API copy-pasted from mk-defsystem. I have gone through excruciating efforts to offer you uiop:run-program that has a decent API and actually works portably. run-shell-command will be actively deprecated starting with ASDF 3.2: first mentioning it will be a style-warning nagware, then a full warning, then a cerror, then it will be gone.
* You don't need dependable-file, there's already static-file
* I don't see why ASDF needs a special recognition for a package-file; there is no way whatsoever that this is useful, and not every system is organized this way, anyway. By contrast, see package-inferred-system.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org A common man marvels at uncommon things; a wise man marvels at the commonplace. — Confucius
l of code for ASDF 1 that is obsolete for ASDF 3, and defines many variants of functions that ASDF 3 already has, such as component-find-path, while using special variables to subvert the system instead of using it.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org
Thanks for valuable comments. Take a look at latest commit:
https://bitbucket.org/budden/budden-tools/src/3cc8612a622055a4ac58be7f496c50...
Most of dead code is deleted.
It looks like what you are building is an extension to ASDF that hooks it into an editor (perhaps specifically the lispworks IDE?). Is that correct?
I've done a patch. decorate-function and decorate-macro are used to apply patches to some parts of asdf.
I use lispworks-tools in Lispworks IDE and swank in SBCL. It is very likely that the code will work in SLIME for every lisp implementation, but I didn't test it.
Also, you might want to split this into modifications/extensions to ASDF and code that interfaces to the Lispworks IDE.
Maybe. This is just a proof of concept. If it can be accepted to master branch of asdf, I'll try to rework it as needed. If not, I can use it as is.
- It is very poor taste to use special variables and redefine
functions to access the current component.
Maybe, but my design goals were: 1. Minimum effort. 2. Maximum portability. 3. Minimum code impact so that I can support the tool if it is not accepted into core of asdf.
Extracting data from error condition seem to be more complex and non-portable. First of all, I know no portable way to access debugger stack. SWANK might help, but task can be rather complicated.
add a restart that doesn't even do the editing for you when it could, why don't you define a handler that adds a restart and re-signals?
What I've done is not so stupid. When we want to edit, re-signalling is unnecessary.
In fact we need context-dependent debugger command in this case, not a handler or restart.
But there is no cross-implementation way to add debugger commands. Also we can't alter "help" command in a debugger so that we could inform the user of an existence of our "edit" command.
Fake restart is just a portable approximation to this desired behaviour.
Maybe I should also issue a warning on the restart like "This restart does nothing. Please read the restart's message".
is not possible, it might make sense to add a restart to ASDF itself, which would actually call the editor instead of hint at it, and where the editor, not the component, is the special variable that the user can thereby customize.
Maybe adding some hook for editing is a good idea. But again, we can discuss it only if we discuss embedding such a tool into asdf itself. What I have now is sufficient for me.
- Do NOT use keywordize and string-equal, use coerce-name and string=.
You're introducing subtle incompatibility in your semantics.
Ok, I changed code of of-system. For M-. symbol seem to be necessary and keywordize is the best thing I can do. Any other ideas?
- I don't see why ASDF needs a special recognition for a package-file;
there is no way whatsoever that this is useful, and not every system is organized this way, anyway. By contrast, see package-inferred-system.
package-file and of-system are irrelevant for current discussion, we can just ignore them for now. I didn't planned to "advertise" them, I simply keep all asdf-related stuff in one file :)
I see my previous reply was unclear
It looks like what you are building is an extension to ASDF
not an extension but a patch
that hooks it into an editor
yes
(perhaps specifically the lispworks IDE?).
No. I use lispworks IDE for Lispworks and EMACS (via SWANK callback) for SBCL. EMACS/SWANK should work with all lisps supported by SLIME.
And one more comment to be as clear as possible :)
My file contains several independent things: 1. package-file, of-system: are not very interesting, lets ignore them.
2. fake restart to allow calling editor from the debugger. The most interesting.
3. tools to enable finding a form definition by system name via M-. in SLIME or Lispworks IDE. Rather useful.
On Wed, Jul 8, 2015 at 5:40 PM, 73budden . budden73@gmail.com wrote:
Take a look at latest commit:
https://bitbucket.org/budden/budden-tools/src/3cc8612a622055a4ac58be7f496c50...
Also, you might want to split this into modifications/extensions to ASDF and code that interfaces to the Lispworks IDE.
Maybe. This is just a proof of concept. If it can be accepted to master branch of asdf, I'll try to rework it as needed. If not, I can use it as is.
ASDF has a history of accepting patches for essential functionality and/or for hooks that make extension easier: asdf-output-translations (née as output-files :around methods in common-lisp-controller or asdf-binary-locations), asdf-bundle (née asdf-ecl), various patches contributed by ITA Software, hooks added for poiu or asdf-dependency-grovel, utilities pulled from xcvb, the package-inferred-system inspired by quick-build, etc.
If your can propose a useful restart, and it indeed can't be added via a handler-bind, then we'll definitely consider it — although the maintainer to convince nowadays is Robert.
The general criterion I've used is that if it's a useful feature that cannot be portably bootstrapped from the existing asdf and cannot be retrofitted without patching the source either, it's probably worth accepting the feature and/or adding a hook that makes it possible to bootstrap it.
That's why I made asdf-bundle or package-inferred-system builtins rather than extensions — because there interface between them and the core requires some tight coupling, and once the proper hook is present, the incremental cost of the entire feature is small, whereas the inconvenience of pulling in an extension and doing it so without breaking something is high. On the other hand, POIU has hooks but isn't in ASDF itself, because it's not portable enough, and the hooks could be kept small while POIU remains somewhat large. (But designing around those hooks was instrumental in the conceptual cleanup of ASDF 3).
- It is very poor taste to use special variables and redefine
functions to access the current component.
Maybe, but my design goals were:
- Minimum effort.
- Maximum portability.
- Minimum code impact so that I can support
the tool if it is not accepted into core of asdf.
Extracting data from error condition seem to be more complex and non-portable. First of all, I know no portable way to access debugger stack. SWANK might help, but task can be rather complicated.
It's actually simple and totally portable. These are not implementation-defined conditions, but ASDF-defined conditions.
You 'access' a debugger stack by using handler-bind and restart-case. Then the user uses the debugger that can use the annotations. This modular design is a great strength of CL.
add a restart that doesn't even do the editing for you when it could, why don't you define a handler that adds a restart and re-signals?
What I've done is not so stupid. When we want to edit, re-signalling is unnecessary.
You don't understand what I said. I was thinking of a handler-bind that does something like (handler-bind ((some-asdf-condition (e) ... (restart-case (error e) (edit-file () :report ... (funcall *editor* (condition-component e)))))) ...)
Thus, you can add new restarts without having to patch the code, by just wrapping your editor's calls to asdf in proper handlers.
In fact we need context-dependent debugger command in this case, not a handler or restart.
restarts are EXACTLY "context-dependent debugger commands".
But there is no cross-implementation way to add debugger commands.
Yes there is, it's called... a restart.
Also we can't alter "help" command in a debugger so that we could inform the user of an existence of our "edit" command.
That's what the restart is for.
Fake restart is just a portable approximation to this desired behaviour.
A real restart beats fake restart any day.
Maybe I should also issue a warning on the restart like "This restart does nothing. Please read the restart's message".
No, just have the restart actually do the editing.
- Do NOT use keywordize and string-equal, use coerce-name and string=.
You're introducing subtle incompatibility in your semantics.
Ok, I changed code of of-system. For M-. symbol seem to be necessary and keywordize is the best thing I can do. Any other ideas?
If this is a limitation in your debugger, by all means, convert to keyword, but then: 1- do something magic (case inversion if it's reversible, or else error?) to convert from string to keyword. 2- use coerce-name (or the reverse of your magic transformation) to o back to system name. What you must not do is silently do the wrong thing when the system name isn't equal to the string-downcase of your keywordification.
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org A successful [software] tool is one that was used to do something undreamed of by its author. — S. C. Johnson