Can you force the activation of another package?

I have a feature in my find-selection package that adds my selection to the find dialog so F3 will use that text in the future. I have a problem though. I can’t access the find-and-replace package to do this until it is activated. So my feature only works when the find-and-replace view has been opened since atom was loaded.

Is there any way for my package to activate the find-and-replace package when mine is activated?

If find-and-replace had the proper settings in package.json it would load when atom loaded. I assume it would be uncool for me to change another package’s package.json file. -grin-

I moved a post to a new topic: How can I determine what command is behind a key?

1 Like

Unless absolutely crucial, no packages should activate until triggered by an activation event. Which is why find-and-replace does not activate when Atom starts. If all packages activated when Atom launched, the startup time would spiral out of control.

Yes, extremely uncool. I’d flag the package as malicious.

Quickly glanced through the API and source code, and I couldn’t find an event being emitted that you could listen for, telling you that find-and-replace has been activated. One might exist though, I could have missed something obvious.
You can try to work around this, by activating the package, from your package’s activate function;

If the user has disabled the find-and-replace package, your attempt to activate it will fail, so you need to handle that scenario gracefully.

1 Like

AFAIK only a deactivated event is dispatched by packages, which is logical as package activation may involve some asynchronous stuff (hence the promise-based API).
In the minimap-find-and-replace package I register to the events that triggers the package activation (see here).
You can always activate the package yourself by triggering an activation event or by calling the corresponding PackageManager method as @thomasjo mentionned.

Yes, atom.packages.activatePackage('find-and-replace'). It returns a promise, so you will need to wait for the promise to be settled before going any further with your scenario.

Technically, all packages load when Atom does. Not all packages activate.

1 Like

Apparently activatePackage is undocumented. It does not show up in an API search. I’ll give that a go.

BTW, there is no need to get an event when it is activated. I just check before I use it.

Yeah, unfortunately the documentation is not complete. One thing that helps me learn some of these things is looking at the specs of official Atom packages. A good place to start is the Whitespace package. It is the package that the Atom team has built as the “how to write basic specs” tutorial.

1 Like

I tried atom.packages.activatePackage 'find-and-replace' and had a problem. It activated the package but the promise was never resolved or rejected. I also tried adding a callback as the second param, ala node, but that was never called either.

I checked the source of the activatePackage method in Packages and it does return a promise, which I knew already. However, the only usages of activatePackage I could find were in package-manager and none of those used the returned promise.

So apparently there is no resolve or reject being called and I’m back to square one. One more bug to add to the list.

F3 is being handled in find-and-replace. I guess I could override F3 and if it doesn’t apply in my scenario then pass the event on up the tree.

BTW, do Macs have F keys? If so is it always used for find next? If not what should I be using to replace F3 on a Mac?

That’s interesting because it works as expected when using it for specs:

Yes, Macs have F keys, but they’re used almost exclusively for media and other system controls than for applications:

Cmd+G is used most often for “find next” in editors on OS X, in my experience.

OK, then I must be doing something stupid.

First of all I was mistaken when I said I could activate find-and-replace. It turns out that the reason the promise didn’t resolve was because it never did activate. It was also never rejected.

As a test, I used generate-package to create the test package and added this code to the activation event …

console.log ' activated before call:', atom.packages.isPackageActive 'find-and-replace'
activate = atom.packages.activatePackage 'find-and-replace'
console.log ' activated after call:', atom.packages.isPackageActive 'find-and-replace'
activate.then ->
  console.log 'resolved'
, (reason) ->
  console.log 'rejected'
setTimeout ->
  console.log ' activated after delay:', atom.packages.isPackageActive 'find-and-replace'
, 5000

… and got this result …

activated before call: false c:\apps\test\lib\
activated after call: false c:\apps\test\lib\
TestView was toggled! c:\apps\test\lib\
activated after delay: false c:\apps\test\lib\

What am I doing wrong?

Edit: This doesn’t matter. I’m giving up on this feature.

I did a quick test:

So I activated the package and obtained the promise. Then I called then on the promise and passed it a simple function. But only when I went to the main window and pressed Cmd+F did the then execute. So it would appear that even when you explicitly activate a package, if it has activation events … those events have to occur before it will actually be activated.

1 Like

So activatePackage should be named notifyOnActivation since that is all it does.

Not a big deal.

1 Like

I just filed to make a activate(state) a truly async method. This would make it more compelling to use atom.packages.activatePackage() from your own package’s activate(state) method.

1 Like

Was atom.packages.activatePackage ever fixed to actually activate something? I can’t get it to work just as I couldn’t before.

I am working on a package manager package (sort of). I need to activate arbitrary packages at arbitrary times.

Also, is there a atom.packages.deActivatePackage?

1 Like

My testing was screwed up. Everything works. All of these…

  • enablePackage
  • disablePackage
  • activatePackage
  • deactivatePackage

Sorry for the trouble and thanks for the help…

In case anyone stumbles on this thread wanting to know how to load and activate packages I thought I’d throw in a bit more detail about the behavior of activatePackage and how to improve that behavior.

If a package has activationCommands defined in package.json then activatePackage will not actually do any activation. It will still wait for a command before activating. This makes it kind of useless, at least for my use case.

After much pain I have written a version of activatePackage that always works. Don’t let the fake activationDeferred promise scare you. activateNow just makes the mistake of assuming the promise exists and tries to resolve it. One ? in activateNow would have made this unnecessary. I might make a PR to atom/atom for this change.

activatePackage: (name) -> 
  if not atom.packages.isPackageActive name
    pack = atom.packages.getLoadedPackage name
    pack.activationDeferred ?= resolve:(->), reject:(->)

I moved a post to a new topic: Need help with writing specs around package activation

1 Like

This thread is gold guys.

I came in looking for an issue but came out understanding why my attempt at the find-and-replace in my spec tests failed miserably. I do find it very confusing / unexpected for what it’s worth.

1 Like

That’s awesome. It should be in the official packages implementation. Maybe something like forceActivatePackage or passing a flag to activatePackage