Moving slider with keyboard

Hello! I am hoping to code the slider to move right using the keypress ‘b’, left using ‘y’, and to submit the answer using ‘g’. I’ve been using both code and the builder to create my task. Currently, my task uses mouse clicks to move the slider, and after some experimenting, I’m still not sure how best to update this.

I am hoping someone might have some code I could adapt for this purpose? Thanks in advance!

edited to add: psychopy version 2023.2.2

Here is the relevant code:
Lines 382-396

    # --- Initialize components for Routine "Fear_Rating" ---
    fear_rating_text = visual.TextStim(win=win, name='fear_rating_text',
        text='',
        font='Open Sans',
        pos=(0, 0), height=0.05, wrapWidth=None, ori=0.0, 
        color='white', colorSpace='rgb', opacity=None, 
        languageStyle='LTR',
        depth=-1.0);
    fear_rating = visual.Slider(win=win, name='fear_rating',
        startValue=0, size=(1.0, 0.1), pos=(0, -0.2), units=win.units,
        labels=["No Fear", "Very High Fear"], ticks=(0, 1, 2, 3, 4, 5, 6), granularity=1.0,
        style='rating', styleTweaks=('triangleMarker',), opacity=1.0,
        labelColor='White', markerColor=[-1.0000, -0.2157, -1.0000], lineColor='White', colorSpace='rgb',
        font='Arial', labelHeight=0.04,
        flip=False, ori=0.0, depth=-2, readOnly=False)

Lines 830-985

    Fear_Ratings_Loop = data.TrialHandler(nReps=1.0, method='sequential', 
        extraInfo=expInfo, originPath=-1,
        trialList=catList,
        seed=None, name='Fear_Ratings_Loop')
    thisExp.addLoop(Fear_Ratings_Loop)  # add the loop to the experiment
    thisFear_Ratings_Loop = Fear_Ratings_Loop.trialList[0]  # so we can initialise stimuli with some values
    # abbreviate parameter names if possible (e.g. rgb = thisFear_Ratings_Loop.rgb)
    if thisFear_Ratings_Loop != None:
        for paramName in thisFear_Ratings_Loop:
            globals()[paramName] = thisFear_Ratings_Loop[paramName]
    
    for thisFear_Ratings_Loop in Fear_Ratings_Loop:
        currentLoop = Fear_Ratings_Loop
        thisExp.timestampOnFlip(win, 'thisRow.t')
        # pause experiment here if requested
        if thisExp.status == PAUSED:
            pauseExperiment(
                thisExp=thisExp, 
                inputs=inputs, 
                win=win, 
                timers=[routineTimer], 
                playbackComponents=[]
        )
        # abbreviate parameter names if possible (e.g. rgb = thisFear_Ratings_Loop.rgb)
        if thisFear_Ratings_Loop != None:
            for paramName in thisFear_Ratings_Loop:
                globals()[paramName] = thisFear_Ratings_Loop[paramName]
        
        # --- Prepare to start Routine "Fear_Rating" ---
        continueRoutine = True
        # update component parameters for each repeat
        thisExp.addData('Fear_Rating.started', globalClock.getTime())
        fear_rating_text.setText("Please use the following scale to rate how fearful " + str(Category) + "s makes you feel")
        fear_rating.reset()
        # keep track of which components have finished
        
        # Run 'Each Frame' code from marker_rand
        # Randomization of the rating marker
        rand = round(normal(3,2),0)
        while (rand < 1) | (rand > 5):
            rand = round(normal(3,2),0)
        fear_rating.markerPos = rand
        Fear_RatingComponents = [fear_rating_text, fear_rating]
        for thisComponent in Fear_RatingComponents:
            thisComponent.tStart = None
            thisComponent.tStop = None
            thisComponent.tStartRefresh = None
            thisComponent.tStopRefresh = None
            if hasattr(thisComponent, 'status'):
                thisComponent.status = NOT_STARTED
        # reset timers
        t = 0
        _timeToFirstFrame = win.getFutureFlipTime(clock="now")
        frameN = -1
        
        # --- Run Routine "Fear_Rating" ---
        routineForceEnded = not continueRoutine
        while continueRoutine:
            # get current time
            t = routineTimer.getTime()
            tThisFlip = win.getFutureFlipTime(clock=routineTimer)
            tThisFlipGlobal = win.getFutureFlipTime(clock=None)
            frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
            # update/draw components on each frame
            
            # *fear_rating_text* updates
            
            # if fear_rating_text is starting this frame...
            if fear_rating_text.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
                # keep track of start time/frame for later
                fear_rating_text.frameNStart = frameN  # exact frame index
                fear_rating_text.tStart = t  # local t and not account for scr refresh
                fear_rating_text.tStartRefresh = tThisFlipGlobal  # on global time
                win.timeOnFlip(fear_rating_text, 'tStartRefresh')  # time at next scr refresh
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'fear_rating_text.started')
                # update status
                fear_rating_text.status = STARTED
                fear_rating_text.setAutoDraw(True)
            
            # if fear_rating_text is active this frame...
            if fear_rating_text.status == STARTED:
                # update params
                pass
            
            # *fear_rating* updates
            
            # if fear_rating is starting this frame...
            if fear_rating.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
                # keep track of start time/frame for later
                fear_rating.frameNStart = frameN  # exact frame index
                fear_rating.tStart = t  # local t and not account for scr refresh
                fear_rating.tStartRefresh = tThisFlipGlobal  # on global time
                win.timeOnFlip(fear_rating, 'tStartRefresh')  # time at next scr refresh
                # add timestamp to datafile
                thisExp.timestampOnFlip(win, 'fear_rating.started')
                # update status
                fear_rating.status = STARTED
                fear_rating.setAutoDraw(True)
            
            # if fear_rating is active this frame...
            if fear_rating.status == STARTED:
                # update params
                pass
            
            # Check fear_rating for response to end Routine
            if fear_rating.getRating() is not None and fear_rating.status == STARTED:
                continueRoutine = False
            
            # check for quit (typically the Esc key)
            if defaultKeyboard.getKeys(keyList=["escape"]):
                thisExp.status = FINISHED
            if thisExp.status == FINISHED or endExpNow:
                endExperiment(thisExp, inputs=inputs, win=win)
                return
            
            # check if all components have finished
            if not continueRoutine:  # a component has requested a forced-end of Routine
                routineForceEnded = True
                break
            continueRoutine = False  # will revert to True if at least one component still running
            for thisComponent in Fear_RatingComponents:
                if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                    continueRoutine = True
                    break  # at least one component has not yet finished
            
            # refresh the screen
            if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
                win.flip()
        
        # --- Ending Routine "Fear_Rating" ---
        for thisComponent in Fear_RatingComponents:
            if hasattr(thisComponent, "setAutoDraw"):
                thisComponent.setAutoDraw(False)
        thisExp.addData('Fear_Rating.stopped', globalClock.getTime())
        Fear_Ratings_Loop.addData('fear_rating.response', fear_rating.getRating())
        Fear_Ratings_Loop.addData('fear_rating.rt', fear_rating.getRT())
        Fear_Ratings_Loop.addData('fear_rating.history', fear_rating.getHistory())
        # the Routine "Fear_Rating" was not non-slip safe, so reset the non-slip timer
        routineTimer.reset()
        thisExp.nextEntry()
        
        if thisSession is not None:
            # if running in a Session with a Liaison client, send data up to now
            thisSession.sendExperimentData()
    # completed 1.0 repeats of 'Fear_Ratings_Loop'
    
    # get names of stimulus parameters
    if Fear_Ratings_Loop.trialList in ([], [None], None):
        params = []
    else:
        params = Fear_Ratings_Loop.trialList[0].keys()
    # save data for this loop
    Fear_Ratings_Loop.saveAsText(filename + 'Fear_Ratings_Loop.csv', delim=',',
        stimOut=params,
        dataOut=['n','all_mean','all_std', 'all_raw'])