Index: src/org/openstreetmap/josm/plugins/PluginSelection.java
===================================================================
--- src/org/openstreetmap/josm/plugins/PluginSelection.java	(revision 2140)
+++ src/org/openstreetmap/josm/plugins/PluginSelection.java	(working copy)
@@ -30,6 +30,7 @@
 import javax.swing.JEditorPane;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
+import javax.swing.JTextField;
 import javax.swing.UIManager;
 import javax.swing.event.HyperlinkEvent;
 import javax.swing.event.HyperlinkListener;
@@ -45,6 +46,13 @@
     private Map<String, PluginInformation> availablePlugins;
     private Map<String, PluginInformation> localPlugins;
 
+    private JTextField txtFilter = null;
+
+    /* Get a copy of PluginPreference's txtField so we can use it for searching */
+    public void passTxtFilter(JTextField filter) {
+        txtFilter = filter;
+    }
+
     public void updateDescription(JPanel pluginPanel) {
         int count = PluginDownloader.downloadDescription();
         if (count > 0) {
@@ -188,6 +196,16 @@
 
         int row = 0;
         for (final PluginInformation plugin : availablePlugins.values()) {
+            if (txtFilter.getText() != null) {
+                /* This is not the plugin you're looking for */
+                final String name = plugin.name;
+                final String desc = plugin.getLinkDescription();
+                if (!filterNameAndDescription(txtFilter, name, desc)) {
+                    continue;
+                }
+            }
+
+
             boolean enabled = (enabledPlugins != null) && enabledPlugins.contains(plugin.name);
             if (pluginMap.get(plugin.name) == null) {
                 pluginMap.put(plugin.name, enabled);
@@ -254,6 +272,21 @@
         pluginPanel.updateUI();
     }
 
+    private static boolean filterNameAndDescription(JTextField filter, final String name, final String description) {
+        final String input[] = filter.getText().split("\\s+");
+        boolean canHas = true;
+
+        // Make 'foo bar' search for 'bar' or 'foo' in both name and description
+        for (String bit : input) {
+            String lc_bit = bit.toLowerCase();
+            if (!name.toLowerCase().contains(lc_bit) && !description.toLowerCase().contains(lc_bit)) {
+                canHas = false;
+            }
+        }
+
+        return canHas;
+    }
+
     private void loadPlugins() {
         availablePlugins = new TreeMap<String, PluginInformation>(new Comparator<String>(){
             public int compare(String o1, String o2) {
Index: src/org/openstreetmap/josm/gui/preferences/PluginPreference.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/PluginPreference.java	(revision 2140)
+++ src/org/openstreetmap/josm/gui/preferences/PluginPreference.java	(working copy)
@@ -16,10 +16,13 @@
 import javax.swing.JButton;
 import javax.swing.JLabel;
 import javax.swing.JList;
+import javax.swing.JTextField;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
 import javax.swing.Scrollable;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.plugins.PluginDownloader;
@@ -39,14 +42,43 @@
     private PreferenceDialog gui;
     private JScrollPane pluginPane;
     private PluginSelection selection = new PluginSelection();
+    private JTextField txtFilter;
 
     public void addGui(final PreferenceDialog gui) {
         this.gui = gui;
         plugin = gui.createPreferenceTab("plugin", tr("Plugins"), tr("Configure available plugins."), false);
+
+        txtFilter = new JTextField();
+        JLabel lbFilter = new JLabel(tr("Search: "));
+        lbFilter.setLabelFor(txtFilter);
+        plugin.add(lbFilter);
+        plugin.add(txtFilter, GBC.eol().fill(GBC.HORIZONTAL));
+        txtFilter.getDocument().addDocumentListener(new DocumentListener(){
+            public void changedUpdate(DocumentEvent e) {
+                action();
+            }
+
+            public void insertUpdate(DocumentEvent e) {
+                action();
+            }
+
+            public void removeUpdate(DocumentEvent e) {
+                action();
+            }
+
+            private void action() {
+                selection.drawPanel(pluginPanel);
+            }
+        });
+        plugin.add(GBC.glue(0,10), GBC.eol());
+
+        /* main plugin area */
         pluginPane = new JScrollPane(pluginPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
         pluginPane.setBorder(null);
         plugin.add(pluginPane, GBC.eol().fill(GBC.BOTH));
         plugin.add(GBC.glue(0,10), GBC.eol());
+
+        /* buttons at the bottom */
         JButton morePlugins = new JButton(tr("Download List"));
         morePlugins.addActionListener(new ActionListener(){
             public void actionPerformed(ActionEvent e) {
@@ -71,6 +103,7 @@
         });
         plugin.add(configureSites, GBC.std());
 
+        selection.passTxtFilter(txtFilter);
         selection.drawPanel(pluginPanel);
     }
 
