From 23db6449542498636c145e83c71a4a466eb62746 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?R=C3=A9my=20Coutable?= <remy@rymai.me>
Date: Wed, 10 Aug 2016 14:12:09 +0200
Subject: [PATCH] Add support for no-op slash commands that appear in
 autocomplete
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The first one is /cc

Signed-off-by: R茅my Coutable <remy@rymai.me>
---
 app/services/slash_commands/interpret_service.rb | 10 +++++++++-
 lib/gitlab/slash_commands/dsl.rb                 | 14 +++++++++++---
 spec/lib/gitlab/slash_commands/dsl_spec.rb       | 16 +++++++++++-----
 spec/lib/gitlab/slash_commands/extractor_spec.rb |  4 ++--
 .../issuable_slash_commands_shared_examples.rb   |  5 ++---
 5 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/app/services/slash_commands/interpret_service.rb b/app/services/slash_commands/interpret_service.rb
index 3030af0599..55b14f118d 100644
--- a/app/services/slash_commands/interpret_service.rb
+++ b/app/services/slash_commands/interpret_service.rb
@@ -117,7 +117,7 @@ module SlashCommands
       return unless noteable.respond_to?(:due_date)
 
       due_date = begin
-        if due_date_param.downcase == 'tomorrow'
+        if due_date_param.casecmp('tomorrow').zero?
           Date.tomorrow
         else
           Time.now + ChronicDuration.parse(due_date_param)
@@ -136,6 +136,14 @@ module SlashCommands
       @updates[:due_date] = nil
     end
 
+    # This is a dummy command, so that it appears in the autocomplete commands
+    desc 'CC'
+    params '@user'
+    noop true
+    command :cc do
+      return
+    end
+
     def find_label_ids(labels_param)
       extract_references(labels_param, :label).map(&:id)
     end
diff --git a/lib/gitlab/slash_commands/dsl.rb b/lib/gitlab/slash_commands/dsl.rb
index 3ded4109f2..edfe840587 100644
--- a/lib/gitlab/slash_commands/dsl.rb
+++ b/lib/gitlab/slash_commands/dsl.rb
@@ -14,8 +14,10 @@ module Gitlab
 
         def command_names
           command_definitions.flat_map do |command_definition|
-            [command_definition[:name], command_definition[:aliases]].flatten
-          end
+            unless command_definition[:noop]
+              [command_definition[:name], command_definition[:aliases]].flatten
+            end
+          end.compact
         end
 
         # Allows to give a description to the next slash command
@@ -28,6 +30,11 @@ module Gitlab
           @params = params
         end
 
+        # Allows to define if a command is a no-op, but should appear in autocomplete
+        def noop(noop)
+          @noop = noop
+        end
+
         # Registers a new command which is recognizeable
         # from body of email or comment.
         # Example:
@@ -63,7 +70,8 @@ module Gitlab
             name: command_name,
             aliases: aliases,
             description: @description || '',
-            params: @params || []
+            params: @params || [],
+            noop: @noop || false
           }
           @command_definitions << command_definition
 
diff --git a/spec/lib/gitlab/slash_commands/dsl_spec.rb b/spec/lib/gitlab/slash_commands/dsl_spec.rb
index f8abb35674..39e1996c89 100644
--- a/spec/lib/gitlab/slash_commands/dsl_spec.rb
+++ b/spec/lib/gitlab/slash_commands/dsl_spec.rb
@@ -29,6 +29,11 @@ describe Gitlab::SlashCommands::Dsl do
       command :wildcard do |*args|
         args
       end
+
+      noop true
+      command :cc do |*args|
+        args
+      end
     end
   end
   let(:dummy) { DummyClass.new }
@@ -36,11 +41,12 @@ describe Gitlab::SlashCommands::Dsl do
   describe '.command_definitions' do
     it 'returns an array with commands definitions' do
       expected = [
-        { name: :no_args, aliases: [:none], description: 'A command with no args', params: [] },
-        { name: :returning, aliases: [], description: 'A command returning a value', params: [] },
-        { name: :one_arg, aliases: [:once, :first], description: '', params: ['The first argument'] },
-        { name: :two_args, aliases: [], description: 'A command with two args', params: ['The first argument', 'The second argument'] },
-        { name: :wildcard, aliases: [], description: '', params: [] }
+        { name: :no_args, aliases: [:none], description: 'A command with no args', params: [], noop: false },
+        { name: :returning, aliases: [], description: 'A command returning a value', params: [], noop: false },
+        { name: :one_arg, aliases: [:once, :first], description: '', params: ['The first argument'], noop: false },
+        { name: :two_args, aliases: [], description: 'A command with two args', params: ['The first argument', 'The second argument'], noop: false },
+        { name: :wildcard, aliases: [], description: '', params: [], noop: false },
+        { name: :cc, aliases: [], description: '', params: [], noop: true }
       ]
 
       expect(DummyClass.command_definitions).to eq expected
diff --git a/spec/lib/gitlab/slash_commands/extractor_spec.rb b/spec/lib/gitlab/slash_commands/extractor_spec.rb
index 11836b1020..ac7296bdba 100644
--- a/spec/lib/gitlab/slash_commands/extractor_spec.rb
+++ b/spec/lib/gitlab/slash_commands/extractor_spec.rb
@@ -175,7 +175,7 @@ describe Gitlab::SlashCommands::Extractor do
     end
 
     it 'does not extract commands inside a blockcode' do
-      msg = msg = "Hello\r\n```\r\nThis is some text\r\n/close\r\n/assign @user\r\n```\r\n\r\nWorld"
+      msg = "Hello\r\n```\r\nThis is some text\r\n/close\r\n/assign @user\r\n```\r\n\r\nWorld"
       expected = msg.delete("\r")
       commands = extractor.extract_commands!(msg)
 
@@ -193,7 +193,7 @@ describe Gitlab::SlashCommands::Extractor do
     end
 
     it 'does not extract commands inside a HTML tag' do
-      msg = msg = "Hello\r\n<div>\r\nThis is some text\r\n/close\r\n/assign @user\r\n</div>\r\n\r\nWorld"
+      msg = "Hello\r\n<div>\r\nThis is some text\r\n/close\r\n/assign @user\r\n</div>\r\n\r\nWorld"
       expected = msg.delete("\r")
       commands = extractor.extract_commands!(msg)
 
diff --git a/spec/support/issuable_slash_commands_shared_examples.rb b/spec/support/issuable_slash_commands_shared_examples.rb
index 4f2e7c3bee..e1255bd248 100644
--- a/spec/support/issuable_slash_commands_shared_examples.rb
+++ b/spec/support/issuable_slash_commands_shared_examples.rb
@@ -28,7 +28,7 @@ shared_examples 'issuable record that supports slash commands in its description
 
         issuable = project.public_send(issuable_type.to_s.pluralize).first
 
-        expect(issuable.description).to eq "bug description\r\n"
+        expect(issuable.description).to eq "bug description\n"
         expect(issuable.labels).to eq [label_bug]
         expect(issuable.milestone).to eq milestone
         expect(page).to have_content 'bug 345'
@@ -57,7 +57,7 @@ shared_examples 'issuable record that supports slash commands in its description
         issuable.reload
         note = issuable.notes.user.first
 
-        expect(note.note).to eq "Awesome!\r\n"
+        expect(note.note).to eq "Awesome!\n"
         expect(issuable.assignee).to eq assignee
         expect(issuable.labels).to eq [label_bug]
         expect(issuable.milestone).to eq milestone
@@ -189,7 +189,6 @@ shared_examples 'issuable record that supports slash commands in its description
         end
 
         it "does not reopen the #{issuable_type}" do
-          current_title = issuable.title
           page.within('.js-main-target-form') do
             fill_in 'note[note]', with: "/title Awesome new title"
             click_button 'Comment'
-- 
2.30.9